* better
[mascara-docs.git] / hw / intel 287 programmers reference manual.txt
blob1c2d01b78a6ebec220baec4b9529ab150a511257
1 INTEL 80287 PROGRAMMER'S REFERENCE MANUAL 1987
3 Intel Corporation makes no warranty for the use of its products and
4 assumes no responsibility for any errors which may appear in this document
5 nor does it make a commitment to update the information contained herein.
7 Intel retains the right to make changes to these specifications at any
8 time, without notice.
10 Contact your local sales office to obtain the latest specifications before
11 placing your order.
13 The following are trademarks of Intel Corporation and may only be used to
14 identify Intel Products:
16 Above, BITBUS, COMMputer, CREDIT, Data Pipeline, FASTPATH, Genius, i, î,
17 ICE, iCEL, iCS, iDBP, iDIS, I²ICE, iLBX, im, iMDDX, iMMX, Inboard, Insite,
18 Intel, intel, intelBOS, Intelevision, inteligent Identifier, inteligent
19 Programming, Intellec, Intellink, iOSP, iPDS, iPSC, iRMX, iSBC, iSBX, iSDM,
20 iSXM, KEPROM, Library Manager, MAP-NET, MCS, Megachassis, MICROMAINFRAME,
21 MULTIBUS, MULTICHANNEL, MULTIMODULE, MultiSERVER, ONCE, OpenNET, OTP,
22 PC-BUBBLE, Plug-A-Bubble, PROMPT, Promware, QUEST, QueX, Quick-Pulse
23 Programming, Ripplemode, RMX/80, RUPI, Seamless, SLD, UPI, and VLSiCEL, and
24 the combination of ICE, iCS, iRMX, iSBC, iSBX, MCS, or UPI and a numerical
25 suffix, 4-SITE.
27 MDS is an ordering code only and is not used as a product name or
28 trademark. MDS(R) is a registered trademark of Mohawk Data Sciences
29 Corporation.
31 *MULTIBUS is a patented Intel bus.
33 Additional copies of this manual or other Intel literature may be obtained
34 from:
36 Intel Corporation
37 Literature Distribution
38 Mail Stop SC6-59
39 3065 Bowers Avenue
40 Santa Clara, CA 95051
42 (c)INTEL CORPORATION 1987   CG-10/86
45 Preface
47 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
49 An Introduction to the 80287
50 This supplement describes the 80287 Numeric Processor Extension (NPX) for
51 the 80286 microprocessor. Below is a brief overview of 80286 concepts, along
52 with some of the nomenclature used throughout this and other Intel
53 publications.
56 The 80286 Microsystem
57 The 80286 is a new VLSI microprocessor system with exceptional capabilities
58 for supporting large-system applications. Based on a new-generation CPU (the
59 Intel 80286), this powerful microsystem is designed to support multiuser
60 reprogrammable and real-time multitasking applications. Its dedicated system
61 support circuits simplify system hardware; sophisticated hardware and
62 software tools reduce both the time and the cost of product development.
64 The 80286 is a virtual-memory microprocessor with on-chip memory management
65 and protection. The 80286 microsystem offers a total-solution approach,
66 enabling you to develop high-speed, interactive, multiuser, multitasking‘‘
67 and multiprocessor‘‘systems more rapidly and at higher performance than ever
68 before.
70   Ž  Reliability and system up-time are becoming increasingly important in
71      all applications. Information must be protected from misuse or
72      accidental loss. The 80286 includes a sophisticated and flexible
73      four-level protection mechanism that isolates layers of operating
74      system programs from application programs to maintain a high degree of
75      system integrity.
77   Ž  The 80286 provides 16 megabytes of physical address space to support
78      today's application requirements. This large physical memory enables
79      the 80286 to keep many large programs and data structures
80      simultaneously in memory for high-speed access.
82   Ž  For applications with dynamically changing memory requirements, such
83      as multiuser business systems, the 80286 CPU provides on-chip memory
84      management and virtual memory support. On an 80286-based system, each
85      user can have up to a gigabyte (2^(30) bytes) of virtual-address space.
86      This large address space virtually eliminates restrictions on the
87      number or size of programs that may be part of the system.
89   Ž  Large multiuser or real-time multitasking systems are easily supported
90      by the 80286. High-performance features, such as a very high-speed
91      task switch, fast interrupt-response time, inter-task protection, and a
92      quick and direct operating system interface, make the 80286 highly
93      suited to multiuser/multitasking applications.
95   Ž  The 80286 has two operating modes: Real-Address mode and
96      Protected-Address mode. In Real-Address mode, the 80286 is fully
97      compatible with the 8086, 8088, 80186, and 80188 microprocessors; all
98      of the extensive libraries of 8086 and 8088 software execute four to
99      six times faster on the 80286, without any modification.
101   Ž  In Protected-Address mode, the advanced memory management and
102      protection features of the 80286 become available, without any
103      reduction in performance. Upgrading 8086 and 8088 application programs
104      to use these new memory management and protection features usually
105      requires only reassembly or recompilation (some programs may require
106      minor modification). This compatibility between 80286 and 8086
107      processor families reduces both the time and the cost of
108      software development.
111 The Organization of This Manual
112 This manual describes the 80287 Numeric Processor Extension (NPX) for the
113 80286 microprocessor. The material in this manual is presented from the
114 perspective of software designers, both at an applications and at a systems
115 software level.
117   Ž  Chapter One, "Overview of Numeric Processing," gives an overview of
118      the 80287 NPX and reviews the concepts of numeric computation using the
119      80287.
121   Ž  Chapter Two, "Programming Numeric Applications," provides detailed
122      information for software designers generating applications for systems
123      containing an 80286 CPU with an 80287 NPX. The 80286/80287 instruction
124      set mnemonics are explained in detail, along with a description of
125      programming facilities for these systems. A comparative 80287
126      programming example is given.
128   Ž  Chapter Three, "System-Level Numeric Programming," provides
129      information of interest to systems software writers, including details
130      of the 80287 architecture and operational characteristics.
132   Ž  Chapter Four, "Numeric Programming Examples," provides several
133      detailed programming examples for the 80287, including conditional
134      branching, the conversion between floating-point values and their ASCII
135      representations, and the calculation of several trigonometric
136      functions. These examples illustrate assembly-language programming on
137      the 80287 NPX.
139   Ž  Appendix A, "Machine Instruction Encoding and Decoding," gives
140      reference information on the encoding of NPX instructions.
142   Ž  Appendix B, "Compatability between the 80287 NPX and the 8087,"
143      describes the differences between the 80287 and the 8087.
145   Ž  Appendix C, "Implementing the IEEE P754 Standard," gives details of
146      the IEEE P754 Standard.
148   Ž  The Glossary defines 80287 and floating-point terminology. Refer to
149      it as needed.
152 Related Publications
153 To best use the material in this manual, readers should be familiar with
154 the operation and architecture of 80286 systems. The following manuals
155 contain information related to the content of this supplement and of
156 interest to programmers of 80287 systems:
158   Ž  Introduction to the 80286, order number 210308
160   Ž  ASM286 Assembly Language Reference Manual, order number 121924
162   Ž  80286 Operating System Writer's Guide, order number 121960
164   Ž  80286 Hardware Reference Manual, order number 210760
166   Ž  Microprocessor and Peripheral Handbook, order number 210844
168   Ž  PL/M-286 User's Guide, order number 121945
170   Ž  80287 Support Library Reference Manual, order number 122129
172   Ž  8086 Software Toolbox Manual, order number 122203 (includes
173      information about 80287 Emulator Software)
175 Notational Conventions
176 This manual uses special notation to represent sub- and superscript
177 characters. Subscript characters are surrounded by {curly brackets}, for
178 example 10{2} = 10 base 2. Superscript characters are preceeded by a caret
179 and enclosed within (parentheses), for example 10^(3) = 10 to the third
180 power.
183 Table of Contents
185 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
187 Preface
189 Chapter 1  Overview of Numeric Processing
191 Introduction to the 80287 Numeric Processor Extension
192     Performance
193     Ease of Use
194     Applications
195     Upgradability
196     Programming Interface
197     Hardware Interface
199 80287 Numeric Processor Architecture
200     The NPX Register Stack
201     The NPX Status Word
202     Control Word
203     The NPX Tag Word
204     The NPX Instruction and Data Pointers
206 Computation Fundamentals
207     Number System
208     Data Types and Formats
209         Binary Integers
210         Decimal Integers
211         Real Numbers
212     Rounding Control
213     Precision Control
214     Infinity Control
216 Special Computational Situations
217     Special Numeric Values
218         Nonnormal Real Numbers
219             Denormals and Gradual Underflow
220             Unnormals‘‘Descendents of Denormal Operands
221         Zeros and Pseudo Zeros
222         Infinity
223         NaN (Not a Number)
224         Indefinite
225         Encoding of Data Types
226     Numeric Exceptions
227         Invalid Operation
228         Zero Divisor
229         Denormalized Operand
230         Numeric Overflow and Underflow
231         Inexact Result
232         Handling Numeric Errors
233             Automatic Exception Handling
234             Software Exception Handling
236 Chapter 2  Programming Numeric Applications
238 The 80287 NPX Instruction Set
239     Compatibility with the 8087 NPX
240     Numeric Operands
241     Data Transfer Instructions
242     Arithmetic Instructions
243     Comparison Instructions
244     Transcendental Instructions
245     Constant Instructions
246     Processor Control Instructions
247     Instruction Set Reference Information
248         Instruction Execution Time
249         Bus Transfers
250         Instruction Length
252 Programming Facilities
253     High-Level Languages
254     PL/M-286
255     ASM286
256         Defining Data
257         Records and Structures
258         Addressing Modes
259     Comparative Programming Example
260     80287 Emulation
262 Concurrent Processing with the 80287
263     Managing Concurrency
264     Instruction Synchronization
265     Data Synchronization
266     Error Synchronization
267         Incorrect Error Synchronization
268         Proper Error Synchronization
270 Chapter 3  System-Level Numeric Programming
272 80287 Architecture
273     Processor Extension Data Channel
274     Real-Address Mode and Protected Virtual-Address Mode
275     Dedicated and Reserved I/O Locations
277 Processor Initialization and Control
278      System Initialization
279      Recognizing the 80287 NPX
280      Configuring the Numerics Environment
281      Initializing the 80287
282      80287 Emulation
283      Handling Numeric Processing Exceptions
284      Simultaneous Exception Response
285      Exception Recovery Examples
287 Chapter 4  Numeric Programming Examples
289 Conditional Branching Examples
291 Exception Handling Examples
293 Floating-Point to ASCII Conversion Examples
294     Function Partitioning
295     Exception Considerations
296     Special Instructions
297     Description of Operation
298     Scaling the Value
299         Inaccuracy in Scaling
300         Avoiding Underflow and Overflow
301         Final Adjustments
302     Output Format
304 Trigonometric Calculation Examples
305     FPTAN and FPREM
306     Cosine Uses Sine Code
308 Appendix A  Machine Instriction Encoding and Decoding
310 Appendix B  Compatibility Between the 80287 NPX and the 8087
312 Appendix C  Implementing The IEEE P754 Standard
314     Options implemented in the 80287
315     Areas of the Standard Implemented in Software
316     Additional Software to Meet the Standard
318 Glossary of 80287 and Floating-Point Terminology
320 Index
323 Figures
325 1-1      Evolution and Performance of Numeric Processors
326 1-2      80287 NPX Block Diagram
327 1-3      80287 Register Set
328 1-4      80287 Status Word
329 1-5      80287 Control Word Format
330 1-6      80287 Tag Word Format
331 1-7      80287 Instruction and Data Pointer Image in Memory
332 1-8      80287 Number System
333 1-9      Data Formats
334 1-10     Projective versus Affine Closure
335 1-11     Arithmetic Example Using Infinity
337 2-1      FSAVE/FRSTOR Memory Layout
338 2-2      FSTENV/FLDENV Memory Layout
339 2-3      Sample 80287 Constants
340 2-4      Status Word RECORD Definition
341 2-5      Structure Definition
342 2-6      Sample PL/M-286 Program
343 2-7      Sample ASM286 Program
344 2-8      Instructions and Register Stack
345 2-9      Synchronizing References to Shared Data
346 2-10     Documenting Data Synchronization
347 2-11     Nonconcurrent FIST Instruction Code Macro
348 2-12     Error Synchronization Examples
350 3-1      Software Routine to Recognize the 80287
352 4-1      Conditional Branching for Compares
353 4-2      Conditional Branching for FXAM
354 4-3      Full-State Exception Handler
355 4-4      Reduced-Latency Exception Handler
356 4-5      Reentrant Exception Handler
357 4-6      Floating-Point to ASCII Conversion Routine
358 4-7      Calculating Trigonometric Functions
361 Tables
363 1-1      Numeric Processing Speed Comparisons
364 1-2      Numeric Data Types
365 1-3      Principal NPX Instructions
366 1-4      Interpreting the NPX Condition Codes
367 1-5      Real Number Notation
368 1-6      Rounding Modes
369 1-7      Denormalization Process
370 1-8      Exceptions Due to Denormal Operands
371 1-9      Unnormal Operands and Results
372 1-10     Zero Operands and Results
373 1-11     Masked Overflow Response with Directed Rounding
374 1-12     Infinity Operands and Results
375 1-13     Binary Integer Encodings
376 1-14     Packed Decimal Encodings
377 1-15     Real and Long Real Encodings
378 1-16     Temporary Real Encodings
379 1-17     Exception Conditions and Masked Responses
381 2-1      Data Transfer Instructions
382 2-2      Arithmetic Instructions
383 2-3      Basic Arithmetic Instructions and Operands
384 2-4      Condition Code Interpretation after FPREM
385 2-5      Comparison Instructions
386 2-6      Condition Code Interpretation after FCOM
387 2-7      Condition Code Interpretation after FTST
388 2-8      FXAM Condition Code Settings
389 2-9      Transcendental Instructions
390 2-10     Constant Instructions
391 2-11     Processor Control Instructions
392 2-12     Key to Operand Types
393 2-13     Execution Penalties
394 2-14     Instruction Set Reference Data
395 2-15     PL/M-286 Built-In Procedures
396 2-16     80287 Storage Allocation Directives
397 2-17     Addressing Mode Examples
399 3-1      NPX Processor State Following Initialization
400 3-2      Precedence of NPX Exceptions
402 A-1      80287 Instruction Encoding
403 A-2      Machine Instruction Decoding Guide
406 Chapter 1  Overview of Numeric Processing
408 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
410 The 80287 NPX is a high-performance numerics processing element that
411 extends the 80286 architecture by adding significant numeric capabilities
412 and direct support for floating-point, extended-integer, and BCD data types.
413 The 80286 CPU with 80287 NPX easily supports powerful and accurate numeric
414 applications through its implementation of the proposed IEEE 754 Standard
415 for Binary Floating-Point Arithmetic.
418 Introduction to the 80287 Numeric Processor Extension
419 The 80287 Numeric Processor Extension (NPX) is highly compatible with its
420 predecessor, the earlier Intel 8087 NPX.
422 The 8087 NPX was designed for use in 8086-family systems. The 8086 was the
423 first microprocessor family to partition the processing unit to permit
424 high-performance numeric capabilities. The 8087 NPX for this processor
425 family implemented a complete numeric processing environment in compliance
426 with the proposed IEEE 754 Floating-Point Standard.
428 With the 80287 Numeric Processor Extension, high-speed numeric computations
429 have been extended to 80286 high-performance multi-tasking and multi-user
430 systems. Multiple tasks using the numeric processor extension are afforded
431 the full protection of the 80286 memory management and protection features.
433 Figure 1-1 illustrates the relative performance of 8-MHz 8086/8087 and
434 80286/80287 systems in executing numerics-oriented applications.
437 Figure 1-1.  Evolution and Performance of Numeric Processors
439     DOUBLE-PRECISION       \x1e                ’‘‘‘‘‘‘‘‘‘‘‘‘‘“
440        WHETSTONE           �                � 80286/80287 �
441       PERFORMANCE          �                ”‘‘‘‘‘‘\a‘‘‘‘‘‘•
442         (KOPS)        200 ‘š‘                  \a
443                            �               \a
444                            �     ’‘‘‘‘‘\a‘‘‘‘‘“
445                            �     � 8086/8087 �
446                            �     ”‘‘‘‘‘‘‘‘‘‘‘•
447                            �
448                       100 ‘š‘
449                            �
450                            �
451                            �
452                            �
453                            ”‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘\x10
454                                        1980         1983
456                                        YEAR INTRODUCED
459 Performance
460 Table 1-1 compares the execution times of several 80287 instructions with
461 the equivalent operations executed in software on an 8-MHz 80286. The
462 software equivalents are highly-optimized assembly-language procedures from
463 the 80287 emulator. As indicated in the table, the 80287 NPX provides about
464 50 to 100 times the performance of software numeric routines on the 80286
465 CPU. An 8-MHz 80287 multiplies 32-bit and 64-bit real numbers in about 11.9
466 and 16.9 microseconds, respectively. Of course, the actual performance of
467 the NPX in a given system depends on the characteristics of the individual
468 application.
470 Although the performance figures shown in table 1-1 refer to operations on
471 real (floating-point) numbers, the 80287 also manipulates fixed-point binary
472 and decimal integers of up to 64 bits or 18 digits, respectively. The 80287
473 can improve the speed of multiple-precision software algorithms for integer
474 operations by 10 to 100 times.
476 Because the 80287 NPX is an extension of the 80286 CPU, no software
477 overhead is incurred in setting up the NPX for computation. The 80287 and
478 80286 processors coordinate their activities in a manner transparent to
479 software. Moreover, built-in coordination facilities allow the 80286 CPU to
480 proceed with other instructions while the 80287 NPX is simultaneously
481 executing numeric instructions. Programs can exploit this concurrency of
482 execution to further increase system performance and throughput.
485 Table 1-1.  Numeric Processing Speed Comparisons
487                                                   Approximate Performance
488                                                   Ratios: 8 MHz 80287 to
489                                                   8 MHz Protected Mode iAPX
490 ’‘‘‘‘‘‘ Floating-Point Instruction ‘‘‘‘‘‘‘‘‘‘‘‘“  using E80287
492 FADD ST,ST (Temp Real)             Addition                1: 42
493 FDIV DWORD PTR (Single-Precision)  Division                1:266
494 FXAM (Stack(0) assumed)            Examine                 1:139
495 FYL2X (Stack(0),(1) assumed)       Logarithm               1: 99
496 FPATAN (Stack(0) assumed)          Arctangent              1:153
497 F2XM1 (Stack (0) assumed)          Exponentiation          1: 41
500 Ease of Use
501 The 80287 NPX offers more than raw execution speed for
502 computation-intensive tasks. The 80287 brings the functionality and power
503 of accurate numeric computation into the hands of the general user.
505 Like the 8087 NPX that preceded it, the 80287 is explicitly designed to
506 deliver stable, accurate results when programmed using straightforward
507 "pencil and paper" algorithms. The IEEE 754 standard specifically addresses
508 this issue, recognizing the fundamental importance of making numeric
509 computations both easy and safe to use.
511 For example, most computers can overflow when two single-precision
512 floating-point numbers are multiplied together and then divided by a third,
513 even if the final result is a perfectly valid 32-bit number. The 80287
514 delivers the correctly rounded result. Other typical examples of
515 undesirable machine behavior in straightforward calculations occur when
516 solving for the roots of a quadratic equation:
518   -b ± ¹(b² - 4ac)
519   ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
520           2a
522 for computing financial rate of return, which involves the expression:
523 (1+i)^(n). On most machines, straightforward algorithms will not deliver
524 consistently correct results (and will not indicate when they are
525 incorrect). To obtain correct results on traditional machines under all
526 conditions usually requires sophisticated numerical techniques that are
527 foreign to most programmers. General application programmers using
528 straightforward algorithms will produce much more reliable programs using
529 the 80287. This simple fact greatly reduces the software investment required
530 to develop safe, accurate computation-based products.
532 Beyond traditional numerics support for scientific applications, the 80287
533 has built-in facilities for commercial computing. It can process decimal
534 numbers of up to 18 digits without round-off errors, performing exact
535 arithmetic on integers as large as 2^(64) or 10^(18). Exact arithmetic is
536 vital in accounting applications where rounding errors may introduce
537 monetary losses that cannot be reconciled.
539 The NPX contains a number of optional facilities that can be invoked by
540 sophisticated users. These advanced features include two models of infinity,
541 directed rounding, gradual underflow, and either automatic or programmed
542 exception-handling facilities.
544 These automatic exception-handling facilities permit a high degree of
545 flexibility in numeric processing software, without burdening the
546 programmer. While performing numeric calculations, the NPX automatically
547 detects exception conditions that can potentially damage a calculation. By
548 default, on-chip exception handlers may be invoked to field these exceptions
549 so that a reasonable result is produced, and execution may proceed without
550 program interruption. Alternatively, the NPX can signal the CPU, invoking a
551 software exception handler whenever various types of exceptions are
552 detected.
555 Applications
556 The NPX's versatility and performance make it appropriate to a broad array
557 of numeric applications. In general, applications that exhibit any of the
558 following characteristics can benefit by implementing numeric processing on
559 the 80287:
561   Ž  Numeric data vary over a wide range of values, or include nonintegral
562      values.
564   Ž  Algorithms produce very large or very small intermediate results.
566   Ž  Computations must be very precise; i.e., a large number of significant
567      digits must be maintained.
569   Ž  Performance requirements exceed the capacity of traditional
570      microprocessors.
572   Ž  Consistently safe, reliable results must be delivered using a
573      programming staff that is not expert in numerical techniques.
575 Note also that the 80287 can reduce software development costs and improve
576 the performance of systems that use not only real numbers, but operate on
577 multiprecision binary or decimal integer values as well.
579 A few examples, which show how the 80287 might be used in specific numerics
580 applications, are described below. In many cases, these types of systems
581 have been implemented in the past with minicomputers. The advent of the
582 80287 brings the size and cost savings of microprocessor technology to these
583 applications for the first time.
585   Ž  Business data processing‘‘The NPX's ability to accept decimal operands
586      and produce exact decimal results of up to 18 digits greatly simplifies
587      accounting programming. Financial calculations that use power functions
588      can take advantage of the 80287's exponentiation and logarithmic
589      instructions.
591   Ž  Process control‘‘The 80287 solves dynamic range problems
592      automatically, and its extended precision allows control functions to
593      be fine-tuned for more accurate and efficient performance. Control
594      algorithms implemented with the NPX also contribute to improved
595      reliability and safety, while the 80287's speed can be exploited in
596      real-time operations.
598   Ž  Computer numerical control (CNC)‘‘The 80287 can move and position
599      machine tool heads with accuracy in real-time. Axis positioning also
600      benefits from the hardware trigonometric support provided by the 80287.
602   Ž  Robotics‘‘Coupling small size and modest power requirements with
603      powerful computational abilities, the NPX is ideal for on-board
604      six-axis positioning.
606   Ž  Navigation‘‘Very small, lightweight, and accurate inertial guidance
607      systems can be implemented with the 80287. Its built-in trigonometric
608      functions can speed and simplify the calculation of position from
610   Ž  Graphics terminals‘‘The 80287 can be used in graphics terminals to
611      locally perform many functions that normally demand the attention of a
612      main computer; these include rotation, scaling, and interpolation. By
613      also using an 82720 Graphics Display Controller to perform high speed
614      data transfers, very powerful and highly self-sufficient terminals can
615      be built from a relatively small number of 80286 family parts.
617   Ž  Data acquisition‘‘The 80287 can be used to scan, scale, and reduce
618      large quantities of data as it is collected, thereby lowering storage
619      requirements and time required to process the data for analysis.
621 The preceding examples are oriented toward traditional numerics
622 applications. There are, in addition, many other types of systems that do
623 not appear to the end user as computational, but can employ the 80287 to
624 advantage. Indeed, the 80287 presents the imaginative system designer with
625 an opportunity similar to that created by the introduction of the
626 microprocessor itself. Many applications can be viewed as numerically-based
627 if sufficient computational power is available to support this view. This
628 is analogous to the thousands of successful products that have been built
629 around "buried" microprocessors, even though the products themselves bear
630 little resemblance to computers.
633 Upgradability
634 The architecture of the 80286 CPU is specifically adapted to allow easy
635 upgradability to use an 80287, simply by plugging in the 80287 NPX. For this
636 reason, designers of 80286 systems may wish to incorporate the 80287 NPX
637 into their designs in order to offer two levels of price and performance at
638 little additional cost.
640 Two features of the 80286 CPU make the design and support of upgradable
641 80286 systems particularly simple:
643   Ž  The 80286 can be programmed to recognize the presence of an 80287 NPX;
644      that is, software can recognize whether it is running on an 80286 or an
645      80287 system.
647   Ž  After determining whether the 80287 NPX is available, the 80286 CPU
648      can be instructed to let the NPX execute all numeric instructions. If
649      an 80287 NPX is not available, the 80286 CPU can emulate all 80287
650      numeric instructions in software. This emulation is completely
651      transparent to the application software‘‘the same object code may be
652      used by both 80286 and 80287 systems. No relinking or recompiling of
653      application software is necessary; the same code will simply execute
654      faster on the 80287 than on the 80286 system.
656 To facilitate this design of upgradable 80286 systems, Intel provides a
657 software emulator for the 80287 that provides the functional equivalent of
658 the 80287 hardware, implemented in software on the 80286. Except for
659 timing, the operation of this 80287 emulator (E80287) is the same as for
660 the 80287 NPX hardware. When the emulator is combined as part of the
661 systems software, the 80286 system with 80287 emulation and the 80286 with
662 80287 hardware are virtually indistinguishable to an application program.
663 This capability makes it easy for software developers to maintain a single
664 set of programs for both systems. System manufacturers can offer the NPX
665 as a simple plug-in performance option without necessitating any changes
666 in the user's software.
669 Programming Interface
670 The 80286/80287 pair is programmed as a single processor; all of the 80287
671 registers appear to a programmer as extensions of the basic 80286 register
672 set. The 80286 has a class of instructions known as ESCAPE instructions, all
673 having a common format. These ESC instructions are numeric instructions for
674 the 80287 NPX. These numeric instructions for the 80287 are simply encoded
675 into the instruction stream along with 80286 instructions.
677 All of the CPU memory-addressing modes may be used in programming the NPX,
678 allowing convenient access to record structures, numeric arrays, and other
679 memory-based data structures. All of the memory management and protection
680 features of the CPU are extended to the NPX as well.
682 Numeric processing in the 80287 centers around the NPX register stack.
683 Programmers can treat these eight 80-bit registers as either a fixed
684 register set, with instructions operating on explicitly-designated
685 registers, or a classical stack, with instructions operating on the top one
686 or two stack elements.
688 Internally, the 80287 holds all numbers in a uniform 80-bit temporary-real
689 format. Operands that may be represented in memory as 16-, 32-, or 64-bit
690 integers, 32-, 64-, or 80-bit floating-point numbers, or 18-digit packed BCD
691 numbers, are automatically converted into temporary-real format as they are
692 loaded into the NPX registers. Computation results are subsequently
693 converted back into one of these destination data formats when they are
694 stored into memory from the NPX registers.
696 Table 1-2 lists each of the seven data types supported by the 80287,
697 showing the data format for each type. All operands are stored in memory
698 with the least significant digits starting at the initial (lowest) memory
699 address. Numeric instructions access and store memory operands using only
700 this initial address. For maximum system performance, all operands should
701 start at even memory addresses.
703 Table 1-3 lists the 80287 instructions by class. No special programming
704 tools are necessary to use the 80287, because all of the NPX instructions
705 and data types are directly supported by the ASM286 Assembler and Intel's
706 appropriate high-level languages.
708 Software routines for the 80287 may be written in ASM286 Assembler or any
709 of the following higher-level languages:
711   PL/M-286
712   PASCAL-286
713   FORTRAN-286
714   C-286
716 In addition, all of the development tools supporting the 8086 and 8087 can
717 also be used to develop software for the 80286 and 80287 operating in
718 Real-Address mode.
720 All of these high-level languages provide programmers with access to the
721 computational power and speed of the 80287 without requiring an
722 understanding of the architecture of the 80286 and 80287 chips. Such
723 architectural considerations as concurrency and data synchronization are
724 handled automatically by these high-level languages. For the ASM286
725 programmer, specific rules for handling these issues are discussed in a
726 later section of this supplement.
729 Table 1-2. Numeric Data Types
731                         Significant
732 Data Type        Bits     Digits     Approximate Range (Decimal)
733                          (Decimal)
735 Word integer      16        4       -32,768 ¾ X ¾ +32,767
736 Short integer     32        9       -2*10^(9) ¾ X ¾ +2*10^(9)
737 Long integer      64        18      -9*10^(18) ¾ X ¾ +9*10^(18)
738 Packed decimal    80        18      -99...99 ¾ X ¾ +99...99 (18 digits)
739 Short real        32        6-7     8.43*10^(-37) ¾ �X� ¾ 3.37*10^(38)
740 Long real         64        15-16   4.19*10^(-307) ¾ �X� ¾ 1.67*10^(308)
741 Temporary real    80        19      3.4*10^(-4932) ¾ �X� ¾ 1.2*10^(4932)
744 Table 1-3.  Principal NPX Instructions
746 Class            Instruction Types
748 Data Transfer    Load (all data types), Store (all data types), Exchange
750 Arithmetic       Add, Subtract, Multiply, Divide, Subtract Reversed, Divide
751                  Reversed, Square Root, Scale, Remainder, Integer Part,
752                  Change Sign, Absolute Value, Extract
754 Comparison       Compare, Examine, Test
756 Transcendental   Tangent, Arctangent, 2^(X) -1, Y*Log{2}(X+1), Y*Log{2}(X)
758 Constants        0, 1, Ò, Log{10}2, Log{e}2, Log{2}10, Log2{e}
760 Processor        Load Control Word, Store Control Word, Store Status Word,
762 Control          Load Environment, Store Environment, Save, Restore, Clear
763                  Exceptions, Initialize, Set Protected Mode
766 Hardware Interface
767 As an extension of the 80286 processor, the 80287 is wired very much in
768 parallel with the 80286 CPU. Four special status signals, PEREQ, PEACK,
769 BUSY, and ERROR, permit the two processors to coordinate their
770 activities. The 80287 NPX also monitors the 80286 S1, S0,
771 COD/INTA, READY, HLDA, and CLK pins to monitor the execution of
772 ESC instructions (numeric instructions) by the 80286.
774 As shown in figure 1-2, the 80287 NPX is divided internally into two
775 processing elements; the Bus Interface Unit (BIU) and the Numeric Execution
776 Unit (NEU). The two units operate independently of one another: the BIU
777 receives and decodes instructions, requests operand transfers with memory,
778 and executes processor control instructions, whereas the NEU processes
779 individual numeric instructions.
781 The BIU handles all of the status and signal lines between the 80287 and
782 the 80286. The NEU executes all instructions that involve the register
783 stack. These instructions include arithmetic, logical, transcendental,
784 constant, and data transfer instructions. The data path in the NEU is 84
785 bits wide (68 fraction bits, 15 exponent bits, and a sign bit), allowing
786 internal operand transfers to be performed at very high speeds.
788 The 80287 executes a single numeric instruction at a time. Before executing
789 most ESC instructions, the 80286 tests the BUSY pin and, before initiating
790 the command, waits until the 80287 indicates that it is not busy. Once
791 initiated, the 80286 continues program execution, while the 80287 executes
792 the numeric instruction. Unlike the 8087, which required a WAIT instruction
793 to test the BUSY signal before each ESC opcode, these WAIT instructions are
794 permissible, but not necessary, in 80287 programs.
796 In all cases, a WAIT or ESC instruction should be inserted after any 80287
797 store to memory (except FSTSW or FSTCW) or load from memory (except FLDENV,
798 FLDCW, or FRSTOR) before the 80286 reads or changes the memory value.
800 When needed, all data transfers between memory and the 80287 NPX are
801 performed by the 80286 CPU, using its Processor Extension Data Channel.
802 Numeric data transfers performed by the 80286 use the same timing as any
803 other bus cycle, and all such transfers come under the supervision of the
804 80286 memory management and protection mechanisms. The 80286 Processor
805 Extension Data Channel and the hardware interface between the 80286 and
806 80287 processors are described in Chapter Six of the 80286 Hardware
807 Reference Manual.
809 From the programmer's perspective, the 80287 can be considered just an
810 extension of the 80286 processor. All interaction between the 80286 and the
811 80287 processors on the hardware level is handled automatically by the 80286
812 and is transparent to the software.
814 To communicate with the 80287, the 80286 uses the reserved I/O port
815 addresses 00F8H, 00FAH, and 00FCH (I/O ports numbered 00F8H through 00FFH
816 are reserved for the 80286/80287 interface). These I/O operations are
817 performed automatically by the 80286 and are distinct from I/O operations
818 that result from program I/O instructions. I/O operations resulting from
819 the execution of ESC instructions are completely transparent to software.
820 Any program may execute ESCAPE (numeric) instructions, without regard to its
821 current I/O Privilege Level (IOPL).
823 To guarantee correct operation of the 80287, programs must not perform any
824 explicit I/O operations to any of the eight ports reserved for the 80287.
825 The IOPL of the 80286 can be used to protect the integrity of 80287
826 computations in multiuser reprogrammable applications, preventing any
827 accidental or other tampering with the 80287 (see Chapter Eight of the 80286
828 Operating System Writer's Guide).
831 Figure 1-2.  80287 NPX Block Diagram
833        ’ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘˜‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ “
834           BUS INTERFACE UNIT                  NUMERIC EXECUTION UNIT
835        �                      �                                                    �
836           ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘“             EXPONENT BUS \x1e      \x1e FRACTION BUS
837        �  � CONTROL WORD �    �     ’‘‘‘‘‘‘‘‘‘‘“    €      €     ’‘‘‘‘‘‘‘‘‘‘‘‘‘“   �
838           –‘‘‘‘‘‘‘‘‘‘‘‘‘‘—          � EXPONENT �\x11��\x10€INTER-€\x11���\x10//PROGRAMMABLE//
839        �  � STATUS WORD  �    �     �  MODULE  �    € FACE €     //   SHIFTER  //  �
840           ”‘‘‘‘‘\x1e‘‘‘‘‘‘‘‘•          ”‘‘‘‘‘‘‘‘‘‘•    €\x11�/��\x10€     ”‘‘‘‘‘‘‘\x1e‘‘‘‘‘•
841        �        €             �  ’‘‘‘‘‘‘‘‘‘‘‘‘“     €  16  €\x11������������…         �
842                 €       NEU      � MICROCODE  �  16 /      €\x11�����ƒ ’‘‘‘‘‘‘‘‘‘‘‘‘“
843        �    ’‘‘‘\x1f‘‘‘‘“INSTRUCTION�CONTROL UNIT�     €      / 68   „\x10� ARITHMETIC � �
844             �        ã����������\x10”‘‘‘‘‘‘‘‘‘‘‘‘•‚����‡      €\x11������ƒ�   MODULE   �
845        �    �  DATA  �        �        ‚�������… 16 /      / 64    €”‘‘‘‘‘\x1e‘‘‘‘‘‘• �
846 Data\x11������\x10� BUFFER �                 € ’‘‘“       €      €\x11����ƒ „������…
847        �    �        �    ’‘‘‘�‘‘‘‘‘‘“ € � ’\x1f“’‘‘‘‘‘\x1f‘‘‘‘‘‘\x1f“    €   ’‘‘‘‘‘‘‘‘‘‘‘“ �
848             �        �\x11��\x10� OPERANDS �\x11… � �T��             �(7) „��\x10� TEMPORARY �
849        �    ”‘‘‘\x1e‘‘‘‘•    �  QUEUE   �   � �A��             � ·      � REGISTERS � �
850                 €\x11‘‘‘‘‘“  ”‘‘‘�‘‘‘‘‘‘•   � �G��             � ·      ”‘‘‘‘‘‘‘‘‘‘‘•
851        �  ’‘‘‘‘‘\x1f‘‘‘“  �                 � � ��  REGISTER   � ·                    �
852 Status\x11���\x10 CONTROL �  ”‘‘‘‘‘‘�‘‘‘‘‘‘‘‘‘‘• �W��   STACK     �
853        �  �         �                      �O��             � ·                    �
854 Address\x11��\x10  UNIT   �         �            �R��             �
855        �  ”‘‘‘‘‘‘‘‘‘•                      �D��\x11‘ 80 BITS ‘\x10�(0)                   �
856                               �            ”‘•”‘‘‘‘‘‘‘‘‘‘‘‘‘•
857        ” ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘™‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ ‘ •
860 80287 Numeric Processor Architecture
861 To the programmer, the 80287 NPX appears as a set of additional registers
862 complementing those of the 80286. These additional registers consist of
864   Ž  Eight individually-addressable 80-bit numeric registers, organized as
865      a register stack
867   Ž  Three sixteen-bit registers containing:
868        an NPX status word
869        an NPX control word
870        a tag word
872   Ž  Four 16-bit registers containing the NPX instruction and data pointers
874 All of the NPX numeric instructions focus on the contents of these NPX
875 registers.
878 The NPX Register Stack
879 The 80287 register stack is shown in figure 1-3. Each of the eight numeric
880 registers in the 80287's register stack is 80 bits wide and is divided into
881 fields corresponding to the NPX's temporary-real data type.
883 Numeric instructions address the data registers relative to the register on
884 the top of the stack. At any point in time, this top-of-stack register is
885 indicated by the ST (Stack Top) field in the NPX status word. Load or push
886 operations decrement ST by one and load a value into the new top register.
887 A store-and-pop operation stores the value from the current ST register and
888 then increments ST by one. Like 80286 stacks in memory, the 80287 register
889 stack grows down toward lower-addressed registers.
891 Many numeric instructions have several addressing modes that permit the
892 programmer to implicitly operate on the top of the stack, or to explicitly
893 operate on specific registers relative to the ST. The ASM286 Assembler
894 supports these register addressing modes, using the expression ST(0), or
895 simply ST, to represent the current Stack Top and ST(i) to specify the ith
896 register from ST in the stack (0 ¾ i ¾ 7). For example, if ST contains 011B
897 (register 3 is the top of the stack), the following statement would add the
898 contents of the top two registers on the stack (registers 3 and 5):
900   FADD   ST, ST(2)
902 The stack organization and top-relative addressing of the numeric registers
903 simplify subroutine programming by allowing routines to pass parameters on
904 the register stack. By using the stack to pass parameters rather than using
905 "dedicated" registers, calling routines gain more flexibility in how they
906 use the stack. As long as the stack is not full, each routine simply loads
907 the parameters onto the stack before calling a particular subroutine to
908 perform a numeric calculation. The subroutine then addresses its parameters
909 as ST, ST(1), etc., even though ST may, for example, refer to physical
910 register 3 in one invocation and physical register 5 in another.
913 Figure 1-3.  80287 Register Set
915                              80287 STACK:                          TAG FIELD
916       79  78    64 63                                           0   1    0
917  R1 ‚����Ð��������Ð����������������������������������������������ƒ ‚������ƒ
918     €SIGN�EXPONENT�                  SIGNIFICAND                 € €      €
919  R2 Ã‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
920  R3 Ã‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
921  R4 Ã‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
922  R5 Ã‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
923  R6 Ã‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
924  R7 Ã‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
925  R8 Ã‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Ñ‘‘‘‘‘Â
926     „����¤��������¤����������������������������������������������… „������…
928                        15                   0
929                        ‚���������������������ƒ
930                        €  CONTROL REGISTER   €
931                        Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
932                        €   STATUS REGISTER   €
933                        Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
934                        €      TAG WORD       €
935                        Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
936                        €                     €
937                        Ã‘INSTRUCTION POINTER‘Â
938                        €                     €
939                        Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
940                        €                     €
941                        Ã‘   DATA POINTER    ‘Â
942                        €                     €
943                        „���������������������…
946 The NPX Status Word
947 The 16-bit status word shown in figure 1-4 reflects the overall state of
948 the 80287. This status word may be stored into memory using the
949 FSTSW/FNSTSW, FSTENV/FNSTENV, and FSAVE/FNSAVE instructions, and can be
950 transferred into the 80286 AX register with the FSTSW AX/FNSTSW AX
951 instructions, allowing the NPX status to be inspected by the CPU.
953 The Busy bit (bit 15) and the BUSY pin indicate whether the 80287's
954 execution unit is idle (B = 0) or is executing a numeric instruction or
955 signalling an exception (B = 1). (The instructions FNSTSW, FNSTSW AX,
956 FNSTENV, and FNSAVE do not set the Busy bit themselves, nor do they require
957 the Busy bit to be clear in order to execute.)
959 The four NPX condition code bits (C{0}-C{3}) are similar to the flags in a
960 CPU: the 80287 updates these bits to reflect the outcome of arithmetic
961 operations. The effect of these instructions on the condition code bits is
962 summarized in table 1-4. These condition code bits are used principally for
963 conditional branching. The FSTSWAX instruction stores the NPX status word
964 directly into the CPU AX register, allowing these condition codes to be
965 inspected efficiently by 80286 code.
967 Bits 12-14 of the status word point to the 80287 register that is the
968 current Stack Top (ST). The significance of the stack top has been described
969 in the section on the Register Stack.
971 Figure 1-4 shows the six error flags in bits 0-5 of the status word. Bit 7
972 is the error summary status (ES) bit. ES is set if any unmasked exception
973 bits are set, and is cleared otherwise. If this bit is set, the ERROR
974 signal is asserted. Bits 0-5 indicate whether the NPX has detected one of
975 six possible exception conditions since these status bits were last cleared
976 or reset.
979 Table 1-4.  Interpreting the NPX Condition Codes
982 Instruction
983 Type            C{3}  C{2}  C{1}  C{0}   Interpretation
985 Compare, Test     0     0     X
986 X = value is not affected by instruction     0    ST
987 ST = Top of stack > Source or 0 (FTST)
988                   0     0     X
989 X = value is not affected by instruction     1    ST
990 ST = Top of stack < Source or 0 (FTST)
991                   1     0     X
992 X = value is not affected by instruction     0    ST
993 ST = Top of stack = Source or 0 (FTST)
994                   1     1     X
995 X = value is not affected by instruction     1    ST
996 ST = Top of stack is not comparable
998 Remainder         Q{1}
999 Q{n} = Quotient bit n following complete reduction (C{2}=0) 0   Q{0}
1000 Q{n} = Quotient bit n following complete reduction (C{2}=0) Q{2}
1001 Q{n} = Quotient bit n following complete reduction (C{2}=0)  Complete reduction with three
1002                                          low bits of quotient in C{0},
1003                                          C{3}, and C{1}
1004                   U
1005 U = value is undefined following instruction    1     U
1006 U = value is undefined following instruction    U
1007 U = value is undefined following instruction   Incomplete Reduction
1009 Examine           0     0     0     0    Valid, positive unnormalized
1010                   0     0     0     1    Invalid, positive, exponent = 0
1011                   0     0     1     0    Valid, negative, unnormalized
1012                   0     0     1     1    Invalid, negative, exponent = 0
1013                   0     1     0     0    Valid, positive, normalized
1014                   0     1     0     1    Infinity, positive
1015                   0     1     1     0    Valid, negative, normalized
1016                   0     1     1     1    Infinity, negative
1017                   1     0     0     0    Zero, positive
1018                   1     0     0     1    Empty Register
1019                   1     0     1     0    Zero, negative
1020                   1     0     1     1    Empty Register
1021                   1     1     0     0    Invalid, positive, exponent = 0
1022                   1     1     0     1    Empty Register
1023                   1     1     1     0    Invalid, negative, exponent = 0
1024                   1     1     1     1    Empty Register
1028 Figure 1-4.  80287 Status Word
1030   15                                     0
1031  ‚�Ð��Ð���Ð��Ð��Ð��Ð��Ð�Ð��Ð��Ð��Ð��Ð��Ð��ƒ            EXCEPTION FLAGS
1032  €B�C3�S T�C2�C1�C0�ES�X�PE�UE�OE�ZE�DE�IE€                (1 = EXCEPTION
1033  „Ф�ФÐÐФ�Ф�Ф�Ф�ФФ�Ф�Ф�Ф�Ф�Ф�Ð…                 HAS OCCURRED)
1034   �  � ���  �  �  �  � �  �  �  �  �  �  ”‘‘‘‘‘‘‘‘‘‘‘  INVALID OPERATION
1035 For definitions, see the section on exception handling.
1036   �  � ���  �  �  �  � �  �  �  �  �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘  DENORMALIZED OPERAND
1037 For definitions, see the section on exception handling.
1038   �  � ���  �  �  �  � �  �  �  �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  ZERO DIVIDE
1039 For definitions, see the section on exception handling.
1040   �  � ���  �  �  �  � �  �  �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  OVERFLOW
1041 For definitions, see the section on exception handling.
1042   �  � ���  �  �  �  � �  �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  UNDERFLOW
1043 For definitions, see the section on exception handling.
1044   �  � ���  �  �  �  � �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  PRECISION
1045 For definitions, see the section on exception handling.
1046   �  � ���  �  �  �  � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  (RESERVED)
1047   �  � ���  �  �  �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  ERROR SUMMARY STATUS
1048 ES is set if any unmasked exception bit is set, cleared or otherwise.
1049   �  ”‘���‘‘™‘‘™‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  CONDITION CODE
1050 See Table 1-4 for condition code interpretation.
1051   �    ”™™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘  STACK TOP POINTER
1052 S T VALUES:
1053       000 = REGISTER 0 IS TOP OF STACK
1054       001 = REGISTER 1 IS TOP OF STACK
1055        ¨             ¨
1056        ¨             ¨
1057       111 = REGISTER 7 IS TOP OF STACK
1058   ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ NEU BUSY
1061 Control Word
1062 The NPX provides the programmer with several processing options, which are
1063 selected by loading a word from memory into the control word. Figure 1-5
1064 shows the format and encoding of the fields in the control word.
1066 The low-order byte of this control word configures the 80287 error and
1067 exception masking. Bits 0-5 of the control word contain individual masks for
1068 each of the six exception conditions recognized by the 80287. The high-order
1069 byte of the control word configures the 80287 processing options, including
1071   Ž  Precision control
1072   Ž  Rounding control
1073   Ž  Infinity control
1075 The Precision control bits (bits 8-9) can be used to set the 80287 internal
1076 operating precision at less than the default precision (64-bit significand).
1077 These control bits can be used to provide compatibility with the
1078 earlier-generation arithmetic processors having less precision than the
1079 80287, as required by the IEEE 754 standard. Setting a lower precision,
1080 however, will not affect the execution time of numeric calculations.
1082 The rounding control bits (bits 10-11) provide for directed rounding and
1083 true chop as well as the unbiased round-to-nearest-even mode specified in
1084 the IEEE 754 standard.
1086 The infinity control bit (bit 12) determines the manner in which the 80287
1087 treats the special values of infinity. Either affine closure (where positive
1088 infinity is distinct from negative infinity) or projective closure (infinity
1089 is treated as a single unsigned quantity) may be specified. These two
1090 alternative views of infinity are discussed in the section on Computation
1091 Fundamentals.
1094 Figure 1-5.  80287 Control Word Format
1096  ‚�����Ð���Ð���Ð���Ð�Ð�Ð��Ð��Ð��Ð��Ð��Ð��ƒ
1097  €X X X�I C�R C�P C�X�X�PM�UM�OM�ZM�DM�IM€    EXCEPTION MASKS
1098  „Ð�Ð�Ф�Ð�¤Ð�ФÐ�ФФФ�Ф�Ф�Ф�Ф�Ф�Ð…      (1 = EXCEPTION IS MASKED)
1099   � � �  �  � � � � � �  �  �  �  �  �  ”‘‘‘‘     INVALID OPERATION
1100   � � �  �  � � � � � �  �  �  �  �  ”‘‘‘‘‘‘‘     DENORMALIZED OPERAND
1101   � � �  �  � � � � � �  �  �  �  ”‘‘‘‘‘‘‘‘‘‘     ZERO DIVIDE
1102   � � �  �  � � � � � �  �  �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘     OVERFLOW
1103   � � �  �  � � � � � �  �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘     UNDERFLOW
1104   � � �  �  � � � � � �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘     PRECISION
1105   � � �  �  � � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ (RESERVED)
1106   � � �  �  � � � � ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ (RESERVED)
1107   � � �  �  � � ”‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ PRECISION CONTROL
1108 PRECISION CONTROL
1109 00 = 24-BIT SIGNIFICAND
1110 01 = RESERVED
1111 10 = 53-BIT SIGNIFICAND
1112 11 = 64-BIT SIGNIFICAND
1113   � � �  �  ”‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ ROUNDING CONTROL
1114 ROUNDING CONTROL
1115 00 = ROUND TO NEAREST OR EVEN
1116 01 = ROUND DOWN (TOWARD -ý)
1117 10 = ROUND UP (TOWARD +ý)
1118 11 = CHOP (TRUNCATE TOWARD ZERO)
1119   � � �  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ INFINITY CONTROL
1120   � � �                                         (0 = PROJECTIVE, 1 = AFFINE)
1121   ”‘™‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ (RESERVED)
1124 The NPX Tag Word
1125 The tag word indicates the contents of each register in the register stack,
1126 as shown in figure 1-6. The tag word is used by the NPX itself in order to
1127 track its numeric registers and optimize performance. Programmers may use
1128 this tag information to interpret the contents of the numeric registers.
1129 The tag values are stored in the tag word corresponding to the physical
1130 registers 0-7. Programmers must use the current Stack Top (ST) pointer
1131 stored in the NPX status word to associate these tag values with the
1132 relative stack registers ST(0) through ST(7).
1135 Figure 1-6.  80287 Tag Word Format
1137   15                                                                    0
1138  ‚��������Ð��������Ð��������Ð��������Ð��������Ð��������Ð��������Ð��������ƒ
1139  € TAG(7) � TAG(6) � TAG(5) � TAG(4) � TAG(3) � TAG(2) � TAG(1) � TAG(0) €
1140  „��������¤��������¤��������¤��������¤��������¤��������¤��������¤��������…
1141  TAG VALUES:
1142     00 = VALID;    01 = ZERO;    10 = INVALID OR INFINITY;   11 = EMPTY
1145 The NPX Instruction and Data Pointers
1146 The NPX instruction and data registers provide support for programmed
1147 exception-handlers. Whenever the 80287 executes a math instruction, the NPX
1148 internally saves the instruction address, the operand address (if present),
1149 and the instruction opcode. The 80287 FSTENV and FSAVE instructions store
1150 this data into memory, allowing exception handlers to determine the precise
1151 nature of any numeric exceptions that may be encountered.
1153 When stored in memory, the instruction and data pointers appear in one of
1154 two formats, depending on the operating mode of the 80287. Figure 1-7 shows
1155 these pointers as they are stored following an FSTENV instruction. In
1156 Real-Address mode, these values are the 20-bit physical address and 11-bit
1157 opcode formatted like the 8087. In Protected mode, these values are the
1158 32-bit virtual addresses used by the program that executed the ESC
1159 instruction.
1161 The instruction address saved in the 80287 will point to any prefixes that
1162 preceded the instruction. This is different from the 8087, for which the
1163 instruction address pointed only to the ESC instruction opcode.
1166 Figure 1-7.  80287 Instruction and Data Pointer Image in Memory
1168                                                        MEMORY OFFSET
1169                       ‚�������������������������������ƒ
1170    REAL MODE          €         CONTROL WORD          € +0
1171                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1172                       €          STATUS WORD          € +2
1173                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1174                       €           TAG WORD            € +4
1175                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1176                       €   INSTRUCTION POINTER(15-0)   € +6
1177                       Ã‘‘‘‘‘‘‘‘‘‘‘˜‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1178                       €INSTRUCTION� �   INSTRUCTION   €
1179                       €  POINTER  �0�     OPCODE      € +8
1180                       €  (19-16)  � �     (10-0)      €
1181                       Ã‘‘‘‘‘‘‘‘‘‘‘™‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1182                       €      DATA POINTER(15-0)       € +10
1183                       Ã‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1184                       €   DATA    �                   €
1185                       €  POINTER  �         0         € +12
1186                       €  (19-16)  �                   €
1187                       „�����������¤�������������������…
1188                        15       12 11                0
1190                                                        MEMORY OFFSET
1191                       ‚�������������������������������ƒ
1192    PROTECTED MODE     €         CONTROL WORD          € +0
1193                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1194                       €          STATUS WORD          € +2
1195                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1196                       €           TAG WORD            € +4
1197                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1198                       €           IP OFFSET           € +6
1199                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1200                       €          CS SELECTOR          € +8
1201                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1202                       €      DATA OPERAND OFFSET      € +10
1203                       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
1204                       €     DATA OPERAND SELECTOR     € +12
1205                       „�������������������������������…
1206                        15                            0
1209 Computation Fundamentals
1210 This section covers 80287 programming concepts that are common to all
1211 applications. It describes the 80287's internal number system and the
1212 various types of numbers that can be employed in NPX programs. The most
1213 commonly used options for rounding, precision, and infinity (selected by
1214 fields in the control word) are described, with exhaustive coverage of less
1215 frequently used facilities deferred to later sections. Exception conditions
1216 that may arise during execution of NPX instructions are also described along
1217 with the options that are available for responding to these exceptions.
1220 Number System
1221 The system of real numbers that people use for pencil and paper
1222 calculations is conceptually infinite and continuous. There is no upper or
1223 lower limit to the magnitude of the numbers one can employ in a calculation,
1224 or to the precision (number of significant digits) that the numbers can
1225 represent. When considering any real number, there is always an infinity of
1226 numbers both larger and smaller. There is also an infinity of numbers
1227 between (i.e., with more significant digits than) any two real numbers. For
1228 example, between 2.5 and 2.6 are 2.51, 2.5897, 2.500001, etc.
1230 While ideally it would be desirable for a computer to be able to operate on
1231 the entire real number system, in practice this is not possible. Computers,
1232 no matter how large, ultimately have fixed-size registers and memories that
1233 limit the system of numbers that can be accommodated. These limitations
1234 determine both the range and the precision of numbers. The result is a set
1235 of numbers that is finite and discrete, rather than infinite and continuous.
1236 This sequence is a subset of the real numbers that is designed to form a
1237 useful approximation of the real number system.
1239 Figure 1-8 superimposes the basic 80287 real number system on a real number
1240 line (decimal numbers are shown for clarity, although the 80287 actually
1241 represents numbers in binary). The dots indicate the subset of real numbers
1242 the 80287 can represent as data and final results of calculations. The
1243 80287's range is approximately ±4.19*10^(-307) to ±1.67*10^(308).
1244 Applications that are required to deal with data and final results outside
1245 this range are rare. For reference, the range of the IBM 370 is about
1246 ±0.54*10^(-78) to ±0.72*10^(76).
1248 The finite spacing in figure 1-8 illustrates that the NPX can represent a
1249 great many, but not all, of the real numbers in its range. There is always a
1250 gap between two adjacent 80287 numbers, and it is possible for the result of
1251 a calculation to fall in this space. When this occurs, the NPX rounds the
1252 true result to a number that it can represent. Thus, a real number that
1253 requires more digits than the 80287 can accommodate (e.g., a 20-digit
1254 number) is represented with some loss of accuracy. Notice also that the
1255 80287's representable numbers are not distributed evenly along the real
1256 number line. In fact, an equal number of representable numbers exists
1257 between successive powers of 2 (i.e., as many representable numbers exist
1258 between 2 and 4 as between 65,536 and 131,072). Therefore, the gaps between
1259 representable numbers are larger as the numbers increase in magnitude. All
1260 integers in the range ±2^(64) (approximately ±10^(18)), however, are exactly
1261 representable.
1263 In its internal operations, the 80287 actually employs a number system that
1264 is a substantial superset of that shown in figure 1-8. The internal format
1265 (called temporary real) extends the 80287's range to about ±3.4*10^(-4932)
1266 to ±1.2*10^(4932), and its precision to about 19 (equivalent decimal)
1267 digits. This format is designed to provide extra range and precision for
1268 constants and intermediate results, and is not normally intended for data
1269 or final results.
1271 From a practical standpoint, the 80287's set of real numbers is
1272 sufficiently large and dense so as not to limit the vast majority of
1273 microprocessor applications. Compared to most computers, including
1274 mainframes, the NPX provides a very good approximation of the real number
1275 system. It is important to remember, however, that it is not an exact
1276 representation, and that arithmetic on real numbers is inherently
1277 approximate.
1279 Conversely, and equally important, the 80287 does perform exact arithmetic
1280 on integer operands. That is, an operation on two integers returns an exact
1281 integral result, provided that the true result is an integer and is in
1282 range. For example, 4 ÷ 2 yields an exact integer, 1 ÷ 3 does not, and
1283 2^(40) * 2^(30) + 1 does not, because the result requires greater than 64
1284 bits of precision.
1287 Figure 1-8.  80287 Number System
1289 |\x11‘‘‘NEGATIVE RANGE (NORMALIZED)‘‘\x10|
1290 |                                  |
1291 |             -5  -4  -3  -2  -1   |
1292 ’‘‘‘˜‘‘‘˜‘“’‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘“
1293 �   �   � ��›››�›››�œœœ�œœœ���������
1294 ”‘‘‘™‘‘‘™‘•”‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘•
1295 \x1e                                  \x1e
1296 �                                  �   ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1297 ”-1.67*10^(308)     -4.19*10^(-307)•   � ‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘       �
1298                                        � �������������œœœœœœœœœœœœœœ       �
1299                                        � �������������œœœœœœœœœœœœœœ       �
1300 |\x11‘‘‘POSITIVE RANGE (NORMALIZED)‘‘\x10|   � ‘‘‘‘\a‘‘‘‘‘‘‘\a‘‘‘‘‘‘‘\a‘‘‘‘‘‘       �
1301 |                                  |   �     \x1e       \x1e                     �
1302 |   1   2   3   4   5              |   �     �\x11‘‘˜‘‘\x10�                     �
1303 ’‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘˜‘‘‘“’‘˜‘‘‘˜‘‘‘“   �     �   �   ” 2.00000000000000000 �
1304 ���������œœœ�œœœ�›››�›››�� �   �   �   �     �   �                         �
1305 ”‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘•”‘™‘‘‘™‘‘‘•   �     �   ”‘‘‘‘ (NOT REPRESENTABLE) �
1306 \x1e     ”‘˜‘•                        \x1e   �     �                             �
1307 �       ”‘‘‘‘‘‘‘‘“                 �   �     ”‘‘‘‘‘‘‘‘ 1.99999999999999999 �
1308 �                �    1.67*10^(308)•   �   PRECISION:  �\x11‘‘ 18 DIGITS ‘‘\x10� �
1309 ”4.19*10^(-307)  ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1312 Data Types and Formats
1313 The 80287 recognizes seven numeric data types, divided into three classes:
1314 binary integers, packed decimal integers, and binary reals. A later section
1315 describes how these formats are stored in memory (the sign is always located
1316 in the highest-addressed byte). Figure 1-9 summarizes the format of each
1317 data type. In the figure, the most significant digits of all numbers (and
1318 fields within numbers) are the leftmost digits. Table 1-5 provides the
1319 range and number of signficant (decimal) digits that each format can
1320 accommodate.
1323 Table 1-5.  Real Number Notation
1325 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1326 �     Notation      �                         Value                        �
1327 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1328 �Ordinary Decimal   �  178.125                                             �
1329 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1330 �Scientific Decimal �  1{\x1e}78125E2                                         �
1331 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1332 �Scientific Binary  �  1{\x1e)0110010001E111                                  �
1333 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1334 �Scientific Binary  �  1{\x1e}0110010001E10000110                             �
1335 �(Biased Exponent)  �                                                      �
1336 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1337 �                   �  Sign     Biased Exponent    Significand             �
1338 �                   –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1339 �80287 Short Real   �                                                      �
1340 �(Normalized)       �  0        10000110        \x1e  01100100010000000000000 �
1341 �                   �                           ”‘‘‘‘1{\x1e}(implicit)        �
1342 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1345 Figure 1-9.  Data Formats
1347                  \x11‘‘‘‘‘‘‘‘ INCREASING SIGNIFICANCE
1348            ‚�Ð���������ƒ
1349     WORD   €S�MAGNITUDE€ (TWO'S
1350  INTEGER   „�¤���������… COMPLEMENT)
1351             15        0
1352            ‚�Ð����������������������ƒ
1353    SHORT   €S�      MAGNITUDE       € (TWO'S
1354  INTEGER   „�¤����������������������… COMPLEMENT)
1355             31                     0
1356            ‚�Ð������������������������������������������������ƒ
1357     LONG   €S�                   MAGNITUDE                    € (TWO'S
1358  INTEGER   „�¤������������������������������������������������… COMPLEMENT)
1359             63                                               0
1360            ‚�Ð���Ð������������������������MAGNITUDE������������������������ƒ
1361   PACKED   €S� X �d17 d16   \a  \a  \a   d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0€
1362  DECIMAL   „�¤���¤���¤���¤�����������¤���¤���¤��¤��¤��¤��¤��¤��¤��¤��¤��¤��…
1363             79   72                                                       0
1364            ‚�Ð��������Ð�������������ƒ
1365    SHORT   €S� BIASED � SIGNIFICAND €
1366     REAL   € �EXPONENT�             €
1367            „�¤������� 
1368 Position of implicit binary point. Integer bit of significand; stored in
1369 temporary real, implicit (always 1) in short and long real ������������…
1370            31        22             0
1371            ‚�Ð������������Ð����������������������������������ƒ
1372     LONG   €S�   BIASED   �           SIGNIFICAND            €
1373     REAL   € �  EXPONENT  �                                  €
1374            „�¤����������� 
1375 Position of implicit binary point. Integer bit of significand; stored in
1376 temporary real, implicit (always 1) in short and long real ���������������������������������…
1377            63             51                                  0
1378            ‚�Ð�������������Ð�Ð���������������������������������������������ƒ
1379  TEMPORARY €S�   BIASED    �1�                  SIGNIFICAND                €
1380  REAL      € �  EXPONENT   � �                                             €
1381            „�¤�������������¤ 
1382 Position of implicit binary point ��������������������������������������������…
1383            79            64 63                                             0
1385  NOTES:
1386     S  = Sign bit (0 = positive, 1 = negative)
1387     dn = Decimal digit (two per byte)
1388     X  = Bits have no significance;
1389          80287 ignores when loading, zeros when storing.
1390     Exponent Bias (normal values):
1391          Short Real:  127  (7FH)
1392          Long Real:  1023  (3FFH)
1393          Temporary Real:  16383  (3FFFH)
1396 Binary Integers
1397 The three binary integer formats are identical except for length, which
1398 governs the range that can be accommodated in each format. The leftmost bit
1399 is interpreted as the number's sign: 0 = positive and 1 = negative. Negative
1400 numbers are represented in standard two's complement notation (the binary
1401 integers are the only 80287 format to use two's complement). The quantity
1402 zero is represented with a positive sign (all bits are 0). The 80287 word
1403 integer format is identical to the 16-bit signed integer data type of the
1404 80286.
1407 Decimal Integers
1408 Decimal integers are stored in packed decimal notation, with two decimal
1409 digits "packed" into each byte, except the leftmost byte, which carries the
1410 sign bit (0 = positive, 1 = negative). Negative numbers are not stored in
1411 two's complement form and are distinguished from positive numbers only by
1412 the sign bit. The most significant digit of the number is the leftmost
1413 digit. All digits must be in the range 0H-9H.
1416 Real Numbers
1417 The 80287 stores real numbers in a three-field binary format that resembles
1418 scientific, or exponential, notation. The number's significant digits are
1419 held in the significand field, the exponent field locates the binary point
1420 within the significant digits (and therefore determines the number's
1421 magnitude), and the sign field indicates whether the number is positive or
1422 negative. (The exponent and significand are analogous to the terms
1423 "characteristic" and "mantissa" used to describe floating point numbers on
1424 some computers.) Negative numbers differ from positive numbers only in the
1425 sign bits of their significands.
1427 Table 1-5 shows how the real number 178.125 (decimal) is stored in the
1428 80287 short real format. The table lists a progression of equivalent
1429 notations that express the same value to show how a number can be converted
1430 from one form to another. The ASM286 and PL/M-286 language translators
1431 perform a similar process when they encounter programmer-defined real number
1432 constants. Note that not every decimal fraction has an exact binary
1433 equivalent. The decimal number 1/10, for example, cannot be expressed
1434 exactly in binary (just as the number 1/3 cannot be expressed exactly in
1435 decimal). When a translator encounters such a value, it produces a rounded
1436 binary approximation of the decimal value.
1438 The NPX usually carries the digits of the significand in normalized form.
1439 This means that, except for the value zero, the significand is an integer
1440 and a fraction as follows:
1442   1{\x1e}fff...ff
1444 where \x1e indicates an assumed binary point. The number of fraction bits
1445 varies according to the real format: 23 for short, 52 for long, and 63 for
1446 temporary real. By normalizing real numbers so that their integer bit is
1447 always a 1, the 80287 eliminates leading zeros in small values (�X� < 1).
1448 This technique maximizes the number of significant digits that can be
1449 accommodated in a significand of a given width. Note that, in the short and
1450 long real formats, the integer bit is implicit and is not actually stored;
1451 the integer bit is physically present in the temporary real format only.
1453 If one were to examine only the signficand with its assumed binary point,
1454 all normalized real numbers would have values between 1 and 2. The exponent
1455 field locates the actual binary point in the significant digits. Just as in
1456 decimal scientific notation, a positive exponent has the effect of moving
1457 the binary point to the right, and a negative exponent effectively moves the
1458 binary point to the left, inserting leading zeros as necessary. An unbiased
1459 exponent of zero indicates that the position of the assumed binary point is
1460 also the position of the actual binary point. The exponent field, then,
1461 determines a real number's magnitude.
1463 In order to simplify comparing real numbers (e.g., for sorting), the 80287
1464 stores exponents in a biased form. This means that a constant is added to
1465 the true exponent described above. The value of this bias is different for
1466 each real format (see figure 1-9). It has been chosen so as to force the
1467 biased exponent to be a positive value. This allows two real numbers
1468 (of the same format and sign) to be compared as if they are unsigned binary
1469 integers. That is, when comparing them bitwise from left to right
1470 (beginning with the leftmost exponent bit), the first bit position that
1471 differs orders the numbers; there is no need to proceed further with the
1472 comparison. A number's true exponent can be determined simply by subtracting
1473 the bias value of its format.
1475 The short and long real formats exist in memory only. If a number in one of
1476 these formats is loaded into an 80287 register, it is automatically
1477 converted to temporary real, the format used for all internal operations.
1478 Likewise, data in registers can be converted to short or long real for
1479 storage in memory. The temporary real format may be used in memory also,
1480 typically to store intermediate results that cannot be held in registers.
1482 Most applications should use the long real form to store real number data
1483 and results; it provides sufficient range and precision to return correct
1484 results with a minimum of programmer attention. The short real format is
1485 appropriate for applications that are constrained by memory, but it should
1486 be recognized that this format provides a smaller margin of safety. It is
1487 also useful for debugging algorithms, because roundoff problems will
1488 manifest themselves more quickly in this format. The temporary real format
1489 should normally be reserved for holding intermediate results, loop
1490 accumulations, and constants. Its extra length is designed to shield final
1491 results from the effects of rounding and overflow/underflow in intermediate
1492 calculations. However, the range and precision of the long real form are
1493 adequate for most microcomputer applications.
1496 Rounding Control
1497 Internally, the 80287 employs three extra bits (guard, round, and sticky
1498 bits) that enable it to represent the infinitely precise true result of a
1499 computation; these bits are not accessible to programmers. Whenever the
1500 destination can represent the infinitely precise true result, the 80287
1501 delivers it. Rounding occurs in arithmetic and store operations when the
1502 format of the destination cannot exactly represent the infinitely precise
1503 true result. For example, a real number may be rounded if it is stored in a
1504 shorter real format, or in an integer format. Or, the infinitely precise
1505 true result may be rounded when it is returned to a register.
1507 The NPX has four rounding modes, selectable by the RC field in the control
1508 word (see figure 1-5). Given a true result b that cannot be represented by
1509 the target data type, the 80287 determines the two representable numbers a
1510 and c that most closely bracket b in value (a < b < c). The processor then
1511 rounds (changes) b to a or to c according to the mode selected by the RC
1512 field as shown in table 1-6. Round introduces an error in a result that is
1513 less than one unit in the last place to which the result is rounded. "Round
1514 to nearest" is the default mode and is suitable for most applications; it
1515 provides the most accurate and statistically unbiased estimate of the true
1516 result. The chop mode is provided for integer arithmetic applications.
1518 "Round up" and "round down" are termed directed rounding and can be used to
1519 implement interval arithmetic. Interval arithmetic generates a certifiable
1520 result independent of the occurrence of rounding and other errors. The upper
1521 and lower bounds of an interval may be computed by executing an algorithm
1522 twice, rounding up in one pass and down in the other.
1525 Table 1-6. Rounding Modes
1527 ’‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1528 �RC Field� Rounding Mode          �  Rounding Action                       �
1529 –‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1530 �   00   � Round to nearest       �  Closer to b of a or c; if equally     �
1531 �        �                        �  close, select even number (the one    �
1532 �        �                        �  whose least significant bit is zero). �
1533 �        �                        �                                        �
1534 �   01   � Round down (toward -ý) � a                                      �
1535 �        �                        �                                        �
1536 �   10   � Round up (toward +ý)   � c                                      �
1537 �        �                        �                                        �
1538 �   11   � Chop (toward 0)        �  Smaller in magnitude of a or c        �
1539 ”‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1541 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
1542 NOTE
1543   a < b < c; a and c are representable, b is not.
1544 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
1547 Precision Control
1548 The 80287 allows results to be calculated with either 64, 53, or 24 bits of
1549 precision in the significand as selected by the precision control (PC) field
1550 of the control word. The default setting, and the one that is best suited
1551 for most applications, is the full 64 bits of significance provided by the
1552 temporary-real format. The other settings are required by the proposed IEEE
1553 standard, and are provided to obtain compatibility with the specifications
1554 of certain existing programming languages. Specifying less precision
1555 nullifies the advantages of the temporary real format's extended fraction
1556 length, and does not increase execution speed. When reduced precision is
1557 specified, the rounding of the fractional value clears the unused bits on
1558 the right to zeros.
1561 Infinity Control
1562 The 80287's system of real numbers may be closed by either of two models of
1563 infinity. These two means of closing the number system, projective and
1564 affine closure, are illustrated schematically in figure 1-10. The setting
1565 of the IC field in the control word selects one model or the other. The
1566 default means of closure is projective, and this is recommended for most
1567 computations. When projective closure is selected, the NPX treats the
1568 special values +ý and -ý as a single unsigned infinity (similar to its
1569 treatment of signed zeros). In the affine mode the NPX respects the signs
1570 of +ý and -ý.
1572 While affine mode may provide more information than projective, there are
1573 occasions when the sign may in fact represent misinformation. For example,
1574 consider an algorithm that yields an intermediate result x of +0 and -0 (the
1575 same numeric value) in different executions. If 1/x were then computed in
1576 affine mode, two entirely different values (+ý and -ý) would result from
1577 numerically identical values of x. Projective mode, on the other hand,
1578 provides less information but never returns misinformation. In general,
1579 then, projective mode should be used globally, with affine mode reserved
1580 for local computations where the programmer can take advantage of the sign
1581 and knows for certain that the nature of the computations will not produce a
1582 misleading result.
1585 Figure 1-10.  Projective versus Affine Closure
1587              PROJECTIVE CLOSURE                AFFINE CLOSURE
1589                      ý
1590                ’‘‘‘‘\x10\a\x11‘‘‘‘“
1591                �           �
1592              - �           � +            -ý      -       +     +ý
1593                �           �              \a\x11‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘\x10\a
1594                ”‘‘‘‘‘š‘‘‘‘‘•                          0
1595                      0
1598 Special Computational Situations
1599 Besides being able to represent positive and negative numbers, the 80287
1600 data formats may be used to describe other entities. These special values
1601 provide extra flexibility, but most users will not need to understand them
1602 in order to use the 80287 successfully. This section describes the special
1603 values that may occur in certain cases and the significance of each. The
1604 80286 exceptions are also described, for writers of exception handlers and
1605 for those interested in probing the limits of computation using the 80287.
1607 The material presented in this section is mainly of interest to programmers
1608 concerned with writing exception handlers. For many readers, this section
1609 can be browsed lightly.
1612 Special Numeric Values
1613 The 80287 data formats encompass encodings for a variety of special values
1614 in addition to the typical real or integer data values that result from
1615 normal calculations. These special values have significance and can express
1616 relevant information about the computations or operations that produced
1617 them. The various types of special values are
1619   Ž  Non-normal real numbers, including
1620        denormals
1621        unnormals
1623   Ž  Zeros and pseudo zeros
1625   Ž  Positive and negative infinity
1627   Ž  NaN (Not-a-Number)
1629   Ž  Indefinite
1631 The following description explains the origins and significance of each of
1632 these special values. Tables 1-12 through 1-15 at the end of this
1633 section show how each of these special values is encoded for each of the
1634 numeric data types.
1637 Nonnormal Real Numbers
1638 As described previously, the 80287 generally stores nonzero real numbers in
1639 normalized floating-point form; that is, the integer (leading) bit of the
1640 significand is always a 1. This bit is explicitly stored in the temporary
1641 real format, and is implicitly assumed to be a one (1{\x1e}) in the short- and
1642 long-real formats. Since leading zeros are eliminated, normalized storage
1643 allows the maximum number of significant digits to be held in a significand
1644 of a given width.
1646 When a floating-point numeric value becomes very close to zero, normalized
1647 storage cannot be used to express the value accurately. To accommodate these
1648 instances, the 80287 can store and operate on reals that are not normalized,
1649 i.e., whose significands contain one or more leading zeros. Nonnormals
1650 typically arise when the result of a calculation yields a value that is too
1651 small to be represented in normal form.
1653 Nonnormal values can exist in one of two forms:
1655   Ž  The floating-point exponent may be stored at its most negative value
1656      (a Denormal),
1658   Ž  The integer bit (and perhaps other leading bits) of the significand
1659      may be zero (an Unnormal).
1661 The leading zeros of nonnormals permit smaller numbers to be represented,
1662 at the cost of some lost precision (the number of significant bits is
1663 reduced by the leading zeros). In typical algorithms, extremely small values
1664 are most likely to be generated as intermediate, rather than final results.
1665 By using the NPX's temporary real format for holding intermediate, values as
1666 small as ±3.4*10^(-4932) can be represented; this makes the occurrence of
1667 nonnormal numbers a rare phenomenon in 80287 applications. Nevertheless, the
1668 NPX can load, store, and operate on nonnormalized real numbers when they do
1669 occur.
1672 Denormals and Gradual Underflow
1673 A denormal is the result of the NPX's response to an underflow exception
1674 when that exception has been masked by the programmer (see the 80287 control
1675 word, figure 1-5). Underflow occurs when the absolute value of a real
1676 number becomes too small to be represented in the destination format, that
1677 is, when the exponent of the true result is too negative to be represented
1678 in the destination format. For example, a true exponent of -130 will cause
1679 underflow if the destination is short real, because -126 is the smallest
1680 exponent this format can accommodate. No underflow would occur if the
1681 destination were long real or temporary real, since these formats can handle
1682 exponents down to -1023 and -16,383, respectively.
1684 Most computers underflow "abruptly:" they simply return a zero result,
1685 which is likely to produce an unacceptable final result if computation
1686 continues. The 80287, on the other hand, underflows "gradually" when the
1687 underflow exception is masked. Gradual underflow is accomplished by
1688 denormalizing the result until it is just within the exponent range of the
1689 destination format. Denormalizing means incrementing the true result's
1690 exponent and inserting a corresponding leading zero in the significand,
1691 shifting the rest of the significand one place to the right. Denormal
1692 values may occur in any of the short-real, long-real, or temporary-real
1693 formats. Table 1-7 illustrates how a result might be denormalized to fit a
1694 short-real destination.
1696 The intent of the 80287's masked response to underflow is to allow
1697 computation to continue without program intervention, while introducing an
1698 error that carries about the same risk of contaminating the final result as
1699 roundoff error. Roundoff (precision) errors occur frequently in real number
1700 calculations; sometimes they spoil the result of computation, but often they
1701 do not. Recognizing that roundoff errors are often nonfatal, computation
1702 usually proceeds, and the programmer inspects the final results to see if
1703 these errors have had a significant effect. The 80287's masked underflow
1704 response allows programmers to treat underflows in a similar manner; the
1705 computation continues and the programmer can examine the final result to
1706 determine if an underflow has had important consequences. (If the underflow
1707 has had a significant effect, an invalid operation will probably be
1708 signalled later in the computation.)
1710 Denormalization produces a denormal or a zero. Denormals are readily
1711 identified by their exponents, which are always the minimum for their
1712 formats; in biased form, this is always the bit string: 00...00. This same
1713 exponent value is also assigned to the zeros, but a denormal has a nonzero
1714 significand. A denormal in a register is tagged special. Tables 1-14 and
1715 1-15 later in this chapter show how denormal values are encoded in each of
1716 the real data formats.
1718 The denormalization process may cause the loss of low-order significand
1719 bits as they are shifted off the right. In a severe case, all the
1720 significand bits of the true result are shifted out and replaced by the
1721 leading zeros. In this case, the result of denormalization is a true zero,
1722 and if the value is in a register, it is tagged as such. However, this is a
1723 comparatively rare occurrence and, in any case, is no worse than "abrupt"
1724 underflow.
1726 Denormals are rarely encountered in most applications. Typical debugged
1727 algorithms generate extremely small results during the evaluation of
1728 intermediate subexpressions; the final result is usually of an appropriate
1729 magnitude for its short or long real destination. If intermediate results
1730 are held in temporary real, as is recommended, the great range of this
1731 format makes underflow very unlikely. Denormals are likely to arise only
1732 when an application generates a great many intermediates, so many that they
1733 cannot be held on the register stack or in temporary real memory variables.
1734 If storage limitations force the use of short or long reals for
1735 intermediates, and small values are produced, underflow may occur, and, if
1736 masked, may generate denormals.
1738 Accessing a denormal may produce an exception as shown in table 1-8. (The
1739 denormalized exception signals that a denormal has been fetched.) Denormals
1740 may have reduced significance due to lost low-order bits, and an option of
1741 the proposed IEEE standard precludes operations on nonnormalized operands.
1742 This option may be implemented in the form of an exception handler that
1743 responds to unmasked denormalized exceptions. Most users will mask this
1744 exception so that computation may proceed; any loss of accuracy will be
1745 analyzed by the user when the final result is delivered.
1747 As table 1-8 shows, the division and remainder operations do not accept
1748 denormal divisors and raise the invalid operation exception. Recall also
1749 that the transcendental instructions require normalized operands and do not
1750 check for exceptions. In all other cases, the NPX converts denormals to
1751 unnormals, and the rules governing unnormal arithmetic then apply
1752 (unnormals are described in the following section).
1755 Table 1-7. Denormalization Process
1757 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1758 �Operation         �  Sign  �  Exponent
1759 Expressed as unbiased, decimal number �    Significand            �
1760 �‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1761 �True Result       �    0   �    -129    �    1{\x1e}01011100...00      �
1762 �Denormalize       �    0   �    -128    �    0{\x1e}101011100...00     �
1763 �Denormalize       �    0   �    -127    �    0{\x1e}0101011100...00    �
1764 �Denormalize       �    0   �    -126    �    0{\x1e}00101011100...00   �
1765 �Denormal Result
1766 Before storing, significand is rounded to 24 bits, integer bit is
1767 dropped, and exponent is biased by adding 126  �    0   �    -126    �    0{\x1e}00101011100...00   �
1768 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1772 Table 1-8. Exceptions Due to Denormal Operands
1774 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
1775 �Operation                    � Exception �   Masked Response            �
1776 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1777 �FLD (short/long real)        �   D       �  Load as equivalent unnormal �
1778 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1779 �Arithmetic (except following)�   D       �  Convert (in a work area)    �
1780 �                             �           �  denormal to equivalent      �
1781 �                             �           �  unnormal and proceed        �
1782 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1783 �Compare and test             �   D       �  Convert (in a work area)    �
1784 �                             �           �  denormal to equivalent      �
1785 �                             �           �  unnormal and proceed        �
1786 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
1787 �Division or FPREM with       �   I       �  Return real indefinite      �
1788 �denormal divisor             �           �                              �
1789 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
1792 Unnormals‘‘Descendents of Denormal Operands
1793 An unnormal is the result of a computation using denormal operands and is
1794 therefore the descendent of the 80287's masked underflow response. An
1795 unnormal may exist only in the temporary real format; it may have any
1796 exponent that a normal value may have (that is, in biased form any nonzero
1797 value), but it is distinguished from a normal by the integer bit of its
1798 significand, which is always 0. An unnormal in a register is tagged valid.
1799 Unnormals are distinct from denormals, which have an exponent of 00...00 in
1800 biased form.
1802 Unnormals allows arithmetic to continue following an underflow while still
1803 retaining their identity as numbers that may have reduced significance. That
1804 is, unnormal operands generate unnormal results, so long as their
1805 unnormality has a significant effect on the result. Unnormals are thus
1806 prevented from "masquerading" as normals, numbers that have full
1807 significance. On the other hand, if an unnormal has an insignificant effect
1808 on a calculation with a normal, the result will be normal. For example,
1809 adding a small unnormal to a large normal yields a normal result. The
1810 converse situation yields an unnormal.
1812 Table 1-9 shows how the instruction set deals with unnormal operands. Note
1813 that the unnormal may be the original operand or a temporary created by the
1814 80287 from a denormal.
1817 Table 1-9. Unnormal Operands and Results
1820 Operation                          Result
1822 Addition/subtraction               Normalization of operand with larger
1823                                    abosolute value determines normalization
1824                                    of result.
1826 Multiplication                     If either operand is unnormal, result
1827                                    is unormal.
1829 Division (unnormal dividend only)  Result is unnormal.
1831 FPREM (unnormal dividend only)     Result if normalized.
1833 Division/FPREM (unnormal           Signal invalid operation.
1834                                    divisor)
1836 Compare/FTST                       Normalize as much as possible before
1837                                    making comparison.
1839 FRNDINT                            Normalize as much as possible before
1840                                    rounding.
1842 FSQRT                              Signal invalid operation.
1844 FST, FSTP (short/long real         If value is above destination's underflow
1845 destination)                       boundary, then signal invalid operation;
1846                                    else signal underflow.
1848 FSTP (temporary real destination)  Store as usual.
1850 FIST, FISTP, FBSTP                 Signal invalid operation.
1852 FLD                                Load as usual.
1854 FXCH                               Exchange as usual.
1856 Transcendental instructions        Undefined; operands must be normal and
1857                                    are not checked.
1860 Zeros and Pseudo Zeros
1861 The value zero in the real and decimal integer formats may be signed either
1862 positive or negative, although the sign of a binary integer zero is always
1863 positive. For computational purposes, the value of zero always behaves
1864 identically, regardless of sign, and typically the fact that a zero may be
1865 signed is transparent to the programmer. If necessary, the FXAM instruction
1866 may be used to determine a zero's sign.
1868 The zeros discussed above are called true zeros; if one of them is loaded
1869 or generated in a register, the register is tagged zero. Table 1-10 lists
1870 the results of instructions executed with zero operands and also shows how a
1871 true zero may be created from nonzero operands.
1873 Only the temporary real format may contain a special class of values called
1874 pseudo zeros. A pseudo zero is an unnormal whose significand is all zeros,
1875 but whose (biased) exponent is nonzero (true zeros have a zero exponent).
1876 Neither is a pseudo zero's exponent all ones, since this encoding is
1877 reserved for infinities and NANs. A pseudo zero result will be produced if
1878 two unnormals, containing a total of more than 64 leading zero bits in their
1879 significands, are multiplied together. This is a remote possibility in most
1880 applications, but it can happen.
1882 Pseudo zero operands behave like unnormals, except in the following cases
1883 where they produce the same results as true zeros:
1885   Ž  Compare and test instructions
1887   Ž  FRNDINT (round to integer)
1889   Ž  Division, where the dividend is either a true zero or a pseudo zero
1890      (the divisor is a pseudo zero)
1892 In addition and subtraction of a pseudo zero and a true zero or another
1893 pseudo zero, the pseudo zero(s) behaves like unnormals, except for the
1894 determination of the result's sign. The sign is determined as shown in table
1895 1-10 for two true zero operands.
1898 Infinity
1899 The real formats support signed representations of infinities. These values
1900 are encoded with a biased exponent of all ones and a significand of
1901 1{\x1e}00...00; if the infinity is in a register, it is tagged special. The
1902 significand distinguishes infinities from NANs, including real indefinite.
1904 A programmer may code an infinity, or it may be created by the NPX as its
1905 masked response to an overflow or a zero divide exception. Note that when
1906 rounding is up or down, the masked response may create the largest valid
1907 value representable in the destination rather than infinity. See table 1-11
1908 for details. As operands, infinities behave somewhat differently depending
1909 on how the infinity control field in the control word is set (see table
1910 1-12). When the projective model of infinity is selected, the infinities
1911 behave as a single unsigned representation; because of this, infinity
1912 cannot be compared with any value except infinity. In affine mode, the signs
1913 of the infinities are observed, and comparisons are possible.
1916 Table 1-10. Zero Operands and Results
1919 Operation/Operands          Result              Operation/Operands      Result
1921 FLD, FBLD
1922 Arithmetic and compare operations with binary integers interpret the
1923 integer sign in the same manner.                                       Division
1924  +0                         +0                   ±0 ÷ ±0                Invalid operation
1925  -0                         -0                   ±X ÷ ±0                Zerodivide
1926 FILD
1927 Arithmetic and compare operations with binary integers interpret the
1928 integer sign in the same manner.                                            +0 ÷ +X, -0 ÷ -X       +0
1929  +0                         +0                   +0 ÷ -X, -0 ÷ +X       -0
1930 FST, FSTP                                        -X ÷ -Y, +X ÷ +Y       +0, underflow
1931 Very small X and very large Y may yield zero, after rounding of true
1932 result. NPX signals underflow to warn that zero has been yielded from
1933 nonzero operands.
1938  +0                         +0                   -X ÷ +Y, +X ÷ -Y       -0, underflow
1939 Very small X and very large Y may yield zero, after rounding of true
1940 result. NPX signals underflow to warn that zero has been yielded from
1941 nonzero operands.
1946  -0                         -0
1947  +X
1948 Severe underflows in storing to short or long real may generate zeros                        +0                  FPREM
1949  -X
1950 Severe underflows in storing to short or long real may generate zeros                        -0                   ±0 rem ±0              Invalid operation
1951 FBSTP                                            ±X rem ±0              Invalid operation
1952  +0                         +0                   +0 rem +X, +0 rem -X   +0
1953  -0                         -0                   -0 rem +X, -0 rem -X   -0
1954 FIST, FISTP                                      +X rem +Y, +X rem -Y   +0
1955 When Y divides into X exactly
1960  +0                         +0                   -X rem -Y, -X rem +Y   -0
1961 When Y divides into X exactly
1966  -0                         +0
1967  +X
1968 Small values (�X� < 1) stored into integers may round to zero                        +0                  FSQRT
1969  -X
1970 Small values (�X� < 1) stored into integers may round to zero                        +0                   -0                     -0
1971                                                  +0                     +0
1972 Addition
1973  +0 plus +0                 +0                  Compare
1974  -0 plus -0                 -0                   ±0: +X                 A < B
1975  +0 plus -0, -0 plus +0     *0
1976 Sign is determined by round mode:
1977    * = + for nearest, up, or chop
1978    * = - for down                  ±0: ±0                 A = B
1979  -X plus +X, +X plus -X     *0
1980 Sign is determined by round mode:
1981    * = + for nearest, up, or chop
1982    * = - for down                  ±0: -X                 A > B
1983  ±0 plus ±X, ±X plus ±0     šX
1984 š = sign of X
1989                                                 FTST
1990 Subtraction                                      ±0                     Zero
1991  +0 minus -0                +0                  FCHS
1992  -0 minus +0                -0                   +0                     -0
1993  +0 minus +0, -0 minus -0   *0
1994 Sign is determined by round mode:
1995    * = + for nearest, up, or chop
1996    * = - for down                  -0                     +0
1997  +X minus +X, -X minus -X   *0
1998 Sign is determined by round mode:
1999    * = + for nearest, up, or chop
2000    * = - for down                 FABS
2001  ±0 minus ±X, ±X minus ±0   šX
2002 š = sign of X                  ±0                     +0
2003                                                 F2XM1
2004 Multiplication                                   +0                     +0
2005  +0 * +0, -0 * -0           +0                   -0                     -0
2006  +0 * -0, -0 * +0           -0                  FRNDINT
2007  +0 * +X, +X * +0           +0                   +0                     +0
2008  +0 * -X, -X * +0           -0                   -0                     -0
2009  -0 * +X, +X * -0           -0                  FXTRACT
2010  -0 * -X, -X * -0           +0                   +0                     Both +0
2011  +X * +Y, -X * -Y           +0, underflow
2012 Very small values of X and Y may yield zeros, after rounding of true
2013 result. NPX signals underflow to warn that zero has been yielded by
2014 nonzero operands.       -0                     Both -0
2015  +X * -Y, -X * +Y           -0, underflow
2016 Very small values of X and Y may yield zeros, after rounding of true
2017 result. NPX signals underflow to warn that zero has been yielded by
2018 nonzero operands.
2024 NaN (Not a Number)
2025 A NaN (Not a Number) is a member of a class of special values that exist in
2026 the real formats only. A NaN has an exponent of 11..11B, may have either
2027 sign, and may have any significand except 1{\x1e}00..00B, which is assigned to
2028 the infinities. A NaN in a register is tagged special.
2030 The 80287 will generate the special NaN, real indefinite, as its masked
2031 response to an invalid operation exception. This NaN is signed negative; its
2032 significand is encoded 1{\x1e}100..00. All other NaNs represent
2033 programmer-created values.
2035 Whenever the NPX uses an operand that is a NaN, it signals an invalid
2036 operation exception in its status word. If this exception is masked in the
2037 80287 control word, the 80287's masked exception response is to return the
2038 NaN as the operation result. If both operands of an instruction are NaNs,
2039 the result is the NaN with the larger absolute value. In this way, a NaN
2040 that enters a computation propagates through the computation and will
2041 eventually be delivered as the final result. Note, however, that the
2042 transcendental instructions do not check their operands, and a NaN will
2043 produce an undefined result.
2045 By unmasking the invalid operation exception, the programmer can use NaNs
2046 to trap to the exception handler. The generality of this approach and the
2047 large number of NaN values that are available provide the sophisticated
2048 programmer with a tool that can be applied to a variety of special
2049 situations.
2051 For example, a compiler could use NaNs as references to uninitialized
2052 (real) array elements. The compiler could preinitialize each array element
2053 with a NaN whose significand contained the index (relative position) of the
2054 element. If an application program attempted to access an element that it
2055 had not initialized, it would use the NaN placed there by the compiler. If
2056 the invalid operation exception were unmasked, an interrupt would occur, and
2057 the exception handler would be invoked. The exception handler could
2058 determine which element had been accessed, since the operand address field
2059 of the exception pointers would point to the NaN, and the NaN would contain
2060 the index number of the array element.
2062 NaNs could also be used to speed up debugging. In its early testing phase,
2063 a program often contains multiple errors. An exception handler could be
2064 written to save diagnostic information in memory whenever it was invoked.
2065 After storing the diagnostic data, it could supply a NaN as the result of
2066 the erroneous instruction, and that NaN could point to its associated
2067 diagnostic area in memory. The program would then continue, creating a
2068 different NaN for each error. When the program ended, the NaN results could
2069 be used to access the diagnostic data saved at the time the errors
2070 occurred. Many errors could thus be diagnosed and corrected in one test run.
2073 Table 1-11. Masked Overflow Response with Directed Rounding
2075 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
2076 �    True Result    �          �                                           �
2077 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘— Rounding �         Result Delivered                  �
2078 �Normalization �Sign�   Mode   �                                           �
2079 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘š‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2080 �Normal        � +  �  Up      � +ý                                        �
2081 �Normal        � +  �  Down    � Largest finite positive number
2082 The largest valid representable reals are encoded:
2083   exponent: 11...10B
2084   significand: (1){\x1e}11...10B           �
2085 �Normal        � -  �  Up      � Largest finite negative number
2086 The largest valid representable reals are encoded:
2087   exponent: 11...10B
2088   significand: (1){\x1e}11...10B           �
2089 �Normal        � -  �  Down    � -ý                                        �
2090 �Unnormal      � +  �  Up      � +ý                                        �
2091 �Unnormal      � -  �  Down    � Largest exponent, result's significand
2092 The significand retains its identity as an unnormal; the true
2093 result is rounded as usual (effectively chopped toward 0 in this
2094 case). The exponent is encoded 11...10B.   �
2095 �Unnormal      � +  �  Up      � Largest exponent, result's significand
2096 The significand retains its identity as an unnormal; the true
2097 result is rounded as usual (effectively chopped toward 0 in this
2098 case). The exponent is encoded 11...10B.   �
2099 �Unnormal      � -  �  Down    � -ý                                        �
2100 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘™‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
2103 Table 1-12. Infinity Operands and Results
2106 Key to symbols used in this table
2107 X = zero or nonzero operand
2108 Y = nonzero operand
2109 * = sign of original operand
2110 š = sign is complement of original operand's sign
2111 Þ = sign is "exclusive or" original operand signs (+ if operands had
2112     same sign, - if operands had different signs)
2115 Operation           Projective Result               Affine Result
2117 Addition
2118  +ý plus +ý         Invalid operation               +ý
2119  -ý plus -ý         Invalid operation               -ý
2120  +ý plus -ý         Invalid operation               Invalid operation
2121  -ý plus +ý         Invalid operation               Invalid operation
2122  ±ý plus ±X         *ý                              *ý
2123  ±X plus ±ý         *ý                              *ý
2125 Subtraction
2126  +ý minus -ý        Invalid operation               +ý
2127  -ý minus +ý        Invalid operation               -ý
2128  +ý minus +ý        Invalid operation               Invalid operation
2129  -ý minus -ý        Invalid operation               Invalid operation
2130  ±ý minus ±X        *ý                              *ý
2131  ±X minus ±ý        šý                              šý
2133 Multiplication
2134  ±ý * ±ý            Þ                               Þ
2135  ±ý * ±Y            Þ                               Þ
2136  ±0 * ±ý, ±ý * ±0   Invalid operation               Invalid operation
2138 Division
2139  ±ý ÷ ±ý            Invalid operation               Invalid operation
2140  ±ý ÷ ±X            Þ                               Þ
2141  ±X ÷ ±ý            Þ                               Þ
2143 FSQRT
2144  -ý                 Invalid operation               Invalid operation
2145  +ý                 Invalid operation               +ý
2147 FPREM
2148  ±ý rem ±ý          Invalid operation               Invalid operation
2149  ±ý rem ±X          Invalid operation               Invalid operation
2150  ±Y rem ±ý          *Y                              *Y
2151  ±0 rem ±ý          *0                              *0
2153 FRNDINT
2154  ±ý                 *ý                              *ý
2156 FSCALE
2157  ±ý scaled by ±ý    Invalid operation               Invalid operation
2158  ±ý scaled by ±X    *ý                              *ý
2159  ±0 scaled by ±ý    *0                              *0
2160  ±Y scaled by ±     Invalid operation               Invalid operation
2162 FXTRACT
2163  ±ý                 Invalid operation               Invalid operation
2165 Compare
2166  ±ý: ±ý             A = B                           -ý < +ý
2167  ±ý: ±Y             A ? B (and) invalid operation   -ý < Y < +ý
2168  ±ý: ±0             A ? B (and) invalid operation   -ý < 0 < +ý
2170 FTST
2171  ±ý                 A ? B (and) invalid operation   *ý
2174 Indefinite
2175 For every 80287 numeric data type, one unique encoding is reserved for
2176 representing the special value indefinite. The 80287 produces this encoding
2177 as its response to a masked invalid-operation exception. In the case of
2178 reals, the indefinite value can be stored and loaded like any NaN, and it
2179 always retains its special identity; programmers are advised not to use this
2180 encoding for any other purpose. Packed decimal indefinite may be stored by
2181 the NPX in a FBSTP instruction; attempting to use this encoding in a FBLD
2182 instruction, however, will have an undefined result. In the binary
2183 integers, the same encoding may represent either indefinite or the largest
2184 negative number supported by the format (-2^(15), -2^(31), or -2^(63)). The
2185 80287 will store this encoding as its masked response to an invalid
2186 operation, or when the value in a source register represents or rounds to
2187 the largest negative integer representable by the destination. In situations
2188 where its origin may be ambiguous, the invalid operation exception flag can
2189 be examined to see if the value was produced by an exception response. When
2190 this encoding is loaded, or used by an integer arithmetic or compare
2191 operation, it is always interpreted as a negative number; thus indefinite
2192 cannot be loaded from a packed decimal or binary integer.
2195 Encoding of Data Types
2196 Tables 1-13 through 1-16 show how each of the special values just
2197 described is encoded for each of the numeric data types. In these tables,
2198 the least-significant bits are shown to the right and are stored in the
2199 lowest memory addresses. The sign bit is always the left-most bit of the
2200 highest-addressed byte.
2203 Table 1-13. Binary Integer Encodings
2205               Class                   Sign         Magnitude
2206     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2207     �         (Largest)                0            11...11
2208     �                                  ¨               ¨
2209 Positives                              ¨               ¨
2210     �                                  ¨               ¨
2211     �         (Smallest)               0            00...01
2212     ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2213                Zero                    0            00...00
2214     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2215     �         (Smallest)               1            11...11
2216     �                                  ¨               ¨
2217 Negatives                              ¨               ¨
2218     �                                  ¨               ¨
2219     �         (Largest/Indefinite
2220 If this encoding is used as a source operand (as in an integer load or
2221 integer arithmetic instruction), the 80287 interprets it as the largest
2222 negative number representable in the format: -2^(15), -2^(31), or -2^(63).
2223 The 80287 will deliver this encoding to an integer destination in two
2224 cases:
2225   1.  If the result is the largest negative number
2226   2.  As the response to a masked invalid operation exception, in which
2227       case it represents the special value integer indefinite.)    1            00...00
2228     ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2229                                     Word:        ‘‘‘15 bits‘‘‘
2230                                     Short:       ‘‘‘31 bits‘‘‘
2231                                     Long:        ‘‘‘63 bits‘‘‘
2234 Table 1-14. Packed Decimal Encodings
2238                                            ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ Magnitude ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
2239             Class          Sign             digit      digit      digit      digit    . . . digit
2240     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2241     �       (Largest)      0       0000000  1 0 0 1    1 0 0 1    1 0 0 1    1 0 0 1  . . . 1 0 0 1
2242     �                      ¨          ¨                              ¨
2243     �                      ¨          ¨                              ¨
2244 Positives                  ¨          ¨                              ¨
2245     �       (Smallest)     0       0000000  0 0 0 0    0 0 0 0    0 0 0 0    0 0 0 0  . . . 0 0 0 1
2246     �
2247     �       Zero           0       0000000  0 0 0 0    0 0 0 0    0 0 0 0    0 0 0 0  . . . 0 0 0 0
2248     ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2249     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2250     �       Zero           1       0000000  0 0 0 0    0 0 0 0    0 0 0 0    0 0 0 0  . . . 0 0 0 0
2251     � 
2252     �       (Smallest)     1       0000000  0 0 0 0    0 0 0 0    0 0 0 0    0 0 0 0  . . . 0 0 0 1
2253 Negatives                  ¨          ¨                              ¨
2254     �                      ¨          ¨                              ¨
2255     �                      ¨          ¨                              ¨
2256     �       (Largest)      1       0000000  1 0 0 1    1 0 0 1    1 0 0 1    1 0 0 1  . . . 1 0 0 1
2257     ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2258        Indefinite
2259 The packed decimal indefinite encoding is stored by FBSTP in response to a
2260 masked invalid operation exception. Attempting to load this value via FBLD
2261 produces an undefined result.         1       1111111  1 1 1 1    1 1 1 1    U U U U
2262 UUUU means bit values are undefined and may contain any value   U U U U  . . . U U U U
2263                            ‘‘‘‘ 1 byte ‘‘‘  ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘ 9 bytes ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2266 Table 1-15. Real and Long Real Encodings
2269                                           Biased      Significand
2270 Integer bit is implied and not stored
2273             Class                Sign     Exponent    {\x1e}ff...ff
2274    ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2275    �                  NaNs        0       11...11     11...11
2276    �                              ¨          ¨           ¨
2277    �                              ¨          ¨           ¨
2278    �                              ¨          ¨           ¨
2279    �                              0       11...11     00...01
2280    �      ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2281    �                  ý           0       11...11     00...00
2282    �      ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2283    �      �           Normals     0       11...10     11...11
2284    �      �                       ¨          ¨           ¨
2285 Positives �                       ¨          ¨           ¨
2286    �      �                       ¨          ¨           ¨
2287    �      �                       0       00...01     00...00
2288    �      �         ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2289    �    Reals         Denormals   0       00...00     11...11
2290    �      �                       ¨          ¨           ¨
2291    �      �                       ¨          ¨           ¨
2292    �      �                       ¨          ¨           ¨
2293    �      �                       0       00...00     00...01
2294    �      �         ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2295    �      �           Zero        0       00...00     00...00
2296    ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2297    ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2298    �      �           Zero        1       00...00     00...00
2299    �      �         ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2300    �      �           Denormals   1       00...00     00...01
2301    �      �                       ¨          ¨           ¨
2302    �      �                       ¨          ¨           ¨
2303    �    Reals                     ¨          ¨           ¨
2304    �      �                       1       00...00     11...11
2305    �      �         ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2306    �      �           Normals     1       00...01     00...00
2307    �      �                       ¨          ¨           ¨
2308    �      �                       ¨          ¨           ¨
2309    �      �                       ¨          ¨           ¨
2310    �      �                       1       11...10     11...11
2311 Negatives ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2312    �                  ý           1       11...11     00...00
2313    �      ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2314    �      �                       1       11...11     00...01
2315    �      �                       ¨          ¨           ¨
2316    �    NaNs                      ¨          ¨           ¨
2317    �      �                       ¨          ¨           ¨
2318    �      �         ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2319    �      �           Indefinite  1       11...11     10...00
2320    �      ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2321    �                              ¨          ¨           ¨
2322    �                              ¨          ¨           ¨
2323    �                              ¨          ¨           ¨
2324    �                              1       11...11     11...11
2325    ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2326                               Short:  � ‘‘‘8 bits‘‘ � ‘‘23 bits‘‘ �
2327                                Long:  � ‘‘11 bits‘‘ � ‘‘52 bits‘‘ �
2330 Table 1-16. Temporary Real Encodings
2333                                         Biased     Significand
2334 Integer bit is implied and not stored
2337             Class              Sign     Exponent   1{\x1e}ff...ff
2338     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2339     �         NaNs              0       11...11    111...11
2340     �                           ¨          ¨          ¨
2341     �                           ¨          ¨          ¨
2342     �                           ¨          ¨          ¨
2343     �                           0       11...11    100...01
2344     �      ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2345     �         ý                 0       11...11    100...00
2346     �      ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2347     �      �                    0       11...10    Normals
2348     �      �                    ¨          ¨       111...11
2349     �      �                    ¨          ¨          ¨
2350     �      �                    ¨          ¨          ¨
2351     �      �                    ¨          ¨          ¨
2352     �      �                    ¨          ¨          ¨
2353     �      �                    ¨          ¨       100...00
2354     �      �                    ¨          ¨     ‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2355 Positives  �                    ¨          ¨       Unnormals
2356     �      �                    ¨          ¨       011...11
2357     �    Reals                  ¨          ¨          ¨
2358     �      �                    ¨          ¨          ¨
2359     �      �                    ¨          ¨          ¨
2360     �      �                    0       00...01    000...00
2361     �      �                                     ‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2362     �      �                                       Denormals
2363     �      �                    0       00...00    011...11
2364     �      �                    ¨          ¨          ¨
2365     �      �                    ¨          ¨          ¨
2366     �      �                    ¨          ¨          ¨
2367     �      �                    0       00...00    000...01
2368     �      –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2369     �      �        Zero        0       00...00    000...00
2370     ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2371     ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2372     �      �        Zero        1       00...00    000...00
2373     �      –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2374     �      �                                       Denormals
2375     �      �                    1       00...00    000...01
2376     �      �                    ¨          ¨          ¨
2377     �      �                    ¨          ¨          ¨
2378     �      �                    ¨          ¨          ¨
2379     �      �                    1       00...00    011...11
2380     �      �                                     ‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2381     �      �                    1       00...01    Unnormals
2382     �      �                    ¨          ¨       000...00
2383     �      �                    ¨          ¨          ¨
2384     �    Reals                  ¨          ¨          ¨
2385     �      �                    ¨          ¨          ¨
2386     �      �                    ¨          ¨       011...11
2387     �      �                    ¨          ¨
2388     �      �                                     ‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2389 Negatives  �                    ¨          ¨       Normals
2390     �      �                    ¨          ¨       100...00
2391     �      �                    ¨          ¨          ¨
2392     �      �                    ¨          ¨          ¨
2393     �      �                    ¨          ¨          ¨
2394     �      �                    1       11...10    11111...11
2395     �      ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2396     �         ý                 1       11...11    100...00
2397     �      ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2398     �      �                    1       11...11    100...00
2399     �      �                    ¨          ¨          ¨
2400     �      �                    ¨          ¨          ¨
2401     �      �                    ¨          ¨          ¨
2402     �      �         ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2403     �     NaNs      Indefinite  1       11...11    110...00
2404     �      �         ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2405     �      �                    ¨          ¨          ¨
2406     �      �                    ¨          ¨          ¨
2407     �      �                    ¨          ¨          ¨
2408     �      �                    1       11...11    111...11
2409     ”‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2410                                      �‘‘15 bits‘‘�‘‘64 bits‘‘�
2413 Numeric Exceptions
2414 Whenever the 80287 NPX attempts a numeric operation with invalid operands
2415 or produces a result that cannot be represented, the 80287 recognizes a
2416 numeric exception condition. Altogether, the 80287 checks for the following
2417 six classes of exceptions while executing numeric instructions:
2419   1.  Invalid operation
2420   2.  Divide-by-zero
2421   3.  Denormalized operand
2422   4.  Numeric overflow
2423   5.  Numeric underflow
2424   6.  Inexact result (precision)
2427 Invalid Operation
2428 The 80287 reports an invalid operation if any of the following occurs:
2430   Ž  An attempt to load a register that is not empty (stack overflow).
2432   Ž  An attempt to pop an operand from an empty register (stack underflow).
2434   Ž  An operand is a NaN.
2436   Ž  The operands cause the operation to be indeterminate (square root of a
2437      negative number, 0/0).
2439 An invalid operation generally indicates a program error.
2442 Zero Divisor
2443 If an instruction attempts to divide a finite nonzero operand by zero, the
2444 80287 will report a zero divide exception.
2447 Denormalized Operand
2448 If an instruction attempts to operate on a denormal, the NPX reports the
2449 denormalized operand exception. This exception allows users to implement in
2450 software an option of the proposed IEEE standard specifying that operands
2451 must be prenormalized before they are used.
2454 Numeric Overflow and Underflow
2455 If the exponent of a numeric result is too large for the destination real
2456 format, the 80287 signals a numeric overflow. Conversely, if the exponent of
2457 a result is too small to be represented in the destination format, a numeric
2458 underflow is signaled. If either of these exceptions occur, the result of
2459 the operation is outside the range of the destination real format.
2461 Typical algorithms are most likely to produce extremely large and small
2462 numbers in the calculation of intermediate, rather than final, results.
2463 Because of the great range of the temporary real format (recommended as the
2464 destination format for intermediates), overflow and underflow are
2465 relatively rare events in most 80287 applications.
2468 Inexact Result
2469 If the result of an operation is not exactly representable in the
2470 destination format, the 80287 rounds the number and reports the precision
2471 exception. For example, the fraction 1/3 cannot be precisely represented in
2472 binary form. This exception occurs frequently and indicates that some
2473 (generally acceptable) accuracy has been lost; it is provided for
2474 applications that need to perform exact arithmetic only.
2477 Handling Numeric Errors
2478 When numeric errors occur, the NPX takes one of two possible courses of
2479 action:
2481   Ž  The NPX can itself handle the error, producing the most reasonable
2482      result and allowing numeric program execution to continue undisturbed.
2484   Ž  A software exception handler can be invoked by the CPU to handle the
2485      error.
2487 Each of the six exception conditions described above has a corresponding
2488 flag bit in the 80287 status word and a mask bit in the 80287 control word.
2489 If an exception is masked (the corresponding mask bit in the control
2490 word = 1), the 80287 takes an appropriate default action and continues with
2491 the computation. If the exception is unmasked (mask = 0), the 80287 asserts
2492 the ERROR output to the 80286 to signal the exception and invoke a
2493 software exception handler.
2495 The NPX reports an exception by setting the corresponding flag in the NPX
2496 status word to 1. The NPX then checks the corresponding exception mask in
2497 the control word to determine if it should "field" the exception (mask = 1),
2498 or if it should signal the exception to the CPU to invoke a software
2499 exception handler (mask = 0).
2501 If the mask is set, the exception is said to be masked (from user
2502 software), and the NPX executes its on-chip masked response for that
2503 exception. If the mask is not set (mask = 0), the exception is unmasked,
2504 and the NPX performs its unmasked response. The masked response always
2505 produces a standard result, then proceeds with the instruction. The unmasked
2506 response always traps to a software exception handler, allowing the CPU to
2507 recognize and take action on the exception. Table 1-17 gives a complete
2508 description of all exception conditions and the NPX's masked response.
2510 Note that when exceptions are masked, the NPX may detect multiple
2511 exceptions in a single instruction, because it continues executing the
2512 instruction after performing its masked response. For example, the 80287
2513 could detect a denormalized operand, perform its masked response to this
2514 exception, and then detect an underflow.
2517 Table 1-17. Exception Conditions and Masked Responses
2520 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2521       Condition                                         Masked Response
2522 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2523                              Invalid Operation
2524 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2525 Source register is tagged empty        Return real indefinite.
2526 (usually due to stack underflow).
2528 Destination register is not tagged     Return real indefinite
2529 empty (usually due to stack            (overwrite destination value).
2530 overflow).
2532 One or both operands is a NaN.         Return NaN with larger absolute
2533                                        value (ignore signs).
2535 (Compare and test operations only):    Set condition codes "not
2536 one or both operands is a NaN.         comparable."
2538 (Addition operations only): closure    Return real indefinite.
2539 is affine and operands are
2540 opposite-signed infinities; or
2541 closure is projective and both
2542 operands are ý (signs immaterial).
2544 (Subtraction operations only):         Return real indefinite.
2545 closure is affine and operands are
2546 like-signed infinities; or closure
2547 is projective and both operands are
2548 ý (signs immaterial).
2550 (Multiplication operations only):      Return real indefinite.
2551 ý * 0; or 0 * ý.
2553 (Division operations only):            Return real indefinite.
2554 ý ÷ ý; or 0 ÷ 0; or 0 ÷ pseudo
2555 zero; or divisor is denormal
2556 or unormal.
2558 (FPREM instruction only): modulus      Return real indefinite, set
2559 (divisor) is unnormal or denormal;     condition code = "complete
2560 or dividend is ý.                      remainder."
2562 (FSQRT instruction only): operand      Return real indefinite.
2563 is nonzero and negative; or operand
2564 is denormal or unnormal; or closure
2565 is affine and operand is -ý; or
2566 closure is projective and operand
2567 is ý.
2569 (Compare operations only): closure     Set condition code = "not
2570 is projective and ý is being           comparable."
2571 compared with 0, a normal or ý.
2573 (FTST instruction only): closure is    Set condition code = "not
2574 projective and operand is ý.           comparable."
2576 (FIST, FISTP instructions only):       Store integer indefinite.
2577 source register is empty, a NaN,
2578 denormal, unnormal, ý, or exceeds
2579 representable range of destination.
2581 (FBSTP instruction only): source       Stored packed decimal
2582 register is empty, a NaN, denormal,    indefinite.
2583 unnormal, ý, or exceeds 18 decimal
2584 digits.
2586 (FST, FSTP instructions only):         Store real indefinite.
2587 destination is short or long real
2588 and source register is an unnormal
2589 with exponent in range.
2591 (FXCH instruction only): one or        Change empty register(s) to
2592 both registers is tagged empty.        real indefinite and then
2593                                        perform exchange.
2597 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2598       Condition                                         Masked Response
2599 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2600                              Denormalized Operand
2601 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2602 (FLD instruction only): source         No special action; load as usual.
2603 operand is denormal.
2605 (Arithmetic operations only): one      Convert (in a work area) the
2606 or both operands is denormal.          operand to the equivalent unnormal
2607                                        and proceed.
2609 (Compare and test operations only):    Convert (in a work area) any
2610 one or both operands is denormal       denormal to the equivalent
2611 or unnormal other than pseudo          unnormal; normalize as much as
2612 zero).                                 possible, and proceed with
2613                                        operation.
2614 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2615                                  Zero Divide
2616 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2617 (Division operations only):            Return ý signed with "exclusive or"
2618 divisor = 0.                           of operand signs.
2619 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2620                                   Overflow
2621 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2622 (Arithmetic operations only):          Return properly signed ý and signal
2623 rounding is nearest or chop, and       precision exception.
2624 exponent of true result > 16,383.
2626 (FST, FSTP instructions only):         Return properly signed ý and signal
2627 rounding is nearest or chop, and       precision exception.
2628 exponent of true result > +127
2629 (short real destination) or > +1023
2630 (long real destination).
2631 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2632                                  Underflow
2633 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2634 (Arithmetic operations only):          Denormalize until exponent rises to
2635 exponent of true result < -16,382      -16,382 (true), round significand
2636 (true).                                to 64 bits. If denormalized rounded
2637                                        significand = 0, then return true
2638                                        0; else, return denormal (tag =
2639                                        special, biased exponent = 0).
2641 (FST, FSTP instructions only):         Denormalize until exponent rises to
2642 destination is short real and          -126 (true), round significand to
2643 exponent of true result < -126         24 bits, store true 0 if
2644 (true).                                denormalized rounded significand = 0;
2645                                        else, store denormal (biased
2646                                        exponent = 0).
2648 (FST, FSTP instructions only):         Denormalize until exponent rises to
2649 destination is long real and           -1022 (true), round significand to
2650 exponent of true result < -1022        53 bits, store true 0 if rounded
2651 (true).                                denormalized significand = 0; else,
2652                                        store denormal (biased exponent = 0).
2653 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2654                                Precision
2655 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2656 True rounding error occurs.            No special action.
2658 Masked response to overflow            No special action.
2659 exception earlier in instruction.
2662 Automatic Exception Handling
2663 As described in the previous section, when the 80287 NPX encounters an
2664 exception condition whose corresponding mask bit in the NPX control word is
2665 set, the NPX automatically performs an internal fix-up (masked-exception)
2666 response. The 80287 NPX has a default fix-up activity for every possible
2667 exception condition it may encounter. These masked-exception responses are
2668 designed to be safe and are generally acceptable for most numeric
2669 applications.
2671 As an example of how even severe exceptions can be handled safely and
2672 automatically using the NPX's default exception responses, consider a
2673 calculation of the parallel resistance of several values using only the
2674 standard formula (figure 1-11). If R{1} becomes zero, the circuit
2675 resistance becomes zero. With the divide-by-zero and precision exceptions
2676 masked, the 80287 NPX will produce the correct result.
2678 By masking or unmasking specific numeric exceptions in the NPX control
2679 word, NPX programmers can delegate responsibility for most exceptions to the
2680 NPX, reserving the most severe exceptions for programmed exception handlers.
2681 Exception-handling software is often difficult to write, and the NPX's
2682 masked responses have been tailored to deliver the most reasonable result
2683 for each condition. For the majority of applications, programmers will find
2684 that masking all exceptions other than Invalid Operation will yield
2685 satisfactory results with the least programming effort. An Invalid
2686 Operation exception normally indicates a fatal error in a program that must
2687 be corrected; this exception should not normally be masked.
2689 The exception flags in the NPX status word provide a cumulative record of
2690 exceptions that have occurred since these flags were last cleared. Once set,
2691 these flags can be cleared only by executing the FCLEX (clear exceptions)
2692 instruction, by reinitializing the NPX, or by overwriting the flags with an
2693 FRSTOR or FLDENV instruction. This allows a programmer to mask all
2694 exceptions (except invalid operation), run a calculation, and then inspect
2695 the status word to see if any exceptions were detected at any point in the
2696 calculation.
2699 Figure 1-11.  Arithmetic Example Using Infinity
2701       �                          �
2702       �                          �
2703       �           R{1}           �
2704       �‘‘‘‘‘‘‘‘‘/\/\/\/‘‘‘‘‘‘‘‘‘‘�                            1
2705       �                          �      EQUIVALENT   =   ‘‘‘‘‘‘‘‘‘‘‘‘
2706       �                          �      RESISTANCE        1    1    1
2707       �           R{2}           �                       ‘‘ + ‘‘ + ‘‘
2708       �‘‘‘‘‘‘‘‘‘/\/\/\/‘‘‘‘‘‘‘‘‘‘�                      R{1} R{2}  R{3}
2709       �                          �
2710       �                          �
2711       �           R{3}           �
2712       ”‘‘‘‘‘‘‘‘‘/\/\/\/‘‘‘‘‘‘‘‘‘‘•
2715 Software Exception Handling
2716 If the NPX encounters an unmasked exception condition, it signals the
2717 exception to the 80286 CPU using the ERROR status line between the two
2718 processors.
2720 The next time the 80286 CPU encounters a WAIT or ESC instruction in its
2721 instruction stream, the 80286 will detect the active condition of the
2722 ERROR status line and automatically trap to an exception response
2723 routine using interrupt #16‘‘the Processor Extension Error exception.
2725 This exception response routine is typically a part of the systems
2726 software. Typical exception responses may include:
2728   Ž  Incrementing an exception counter for later display or printing
2730   Ž  Printing or displaying diagnostic information (e.g., the 80287
2731      environment and registers)
2733   Ž  Aborting further execution
2735   Ž  Using the exception pointers to build an instruction that will run
2736      without exception andexecuting it
2738 Application programmers on 80286 systems having systems software support
2739 for the 80287 NPX should consult their references for the appropriate system
2740 response to NPX exceptions. For systems programmers, specific details on
2741 writing software exception handlers are included in the section
2742 "System-Level Numeric Programming" later in this manual.
2744 The 80287 NPX differs from the 8087 NPX in the manner in which numeric
2745 exceptions are signalled to the CPU; the 8087 requires an interrupt
2746 controller (8259A) to interrupt the CPU, while the 80287 does not.
2747 Programmers upgrading 8087 software to operate on an 80287 should be aware
2748 of these differences and any implications they might have on numeric
2749 exception-handling software. Appendix B explains the differences between
2750 the 80287 and the 8087 NPX in greater detail.
2753 Chapter 2  Programming Numeric Applications
2755 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
2757 Programmers developing applications for the 80287 have a wide range of
2758 instructions and programming alternatives from which to choose.
2760 The following sections describe the 80287 instruction set in detail, and
2761 follow up with a discussion of several of the programming facilities that
2762 are available to programmers of 80287.
2765 The 80287 NPX Instruction Set
2766 This section describes the operation of all 80287 instructions. Within this
2767 section, the instructions are divided into six functional classes:
2769   Ž  Data Transfer instructions
2770   Ž  Arithmetic instructions
2771   Ž  Comparison instructions
2772   Ž  Transcendental instructions
2773   Ž  Constant instructions
2774   Ž  Processor Control instructions
2776 At the end of this section, each of the instructions is described in terms
2777 of its execution speed, bus transfers, and exceptions, as well as a coding
2778 example for each combination of operands accepted by the instruction. For
2779 easy reference, this information is concentrated into a table, organized
2780 alphabetically by instruction mnemonic.
2782 Throughout this section, the instruction set is described as it appears to
2783 the ASM286 programmer who is coding a program. Appendix A covers the actual
2784 machine instruction encodings, which are principally of use to those reading
2785 unformatted memory dumps, monitoring instruction fetches on the bus, or
2786 writing exception handlers.
2789 Compatibility with the 8087 NPX
2790 The instruction set for the 80287 NPX is largely the same as that for the
2791 8087 NPX used with 8086 and 8088 systems. Most object programs generated for
2792 the 8087 will execute without change on the 80287. Several instructions are
2793 new to the 80287, and several 8087 instructions perform no useful function
2794 on the 80287. Appendix B at the back of this manual gives details of these
2795 instruction set differences and of the differences in the ASM86 and ASM286
2796 assemblers.
2799 Numeric Operands
2800 The typical NPX instruction accepts one or two operands as inputs, operates
2801 on these, and produces a result as an output. Operands are most often (the
2802 contents of) register or memory locations. The operands of some instructions
2803 are predefined; for example, FSQRT always takes the square root of the
2804 number in the top stack element. Others allow, or require, the programmer to
2805 explicitly code the operand(s) along with the instruction mnemonic. Still
2806 others accept one explicit operand and one implicit operand, which is
2807 usually the top stack element.
2809 Whether supplied by the programmer or utilized automatically, the two basic
2810 types of operands are sources and destinations. A source operand simply
2811 supplies one of the inputs to an instruction; it is not altered by the
2812 instruction. Even when an instruction converts the source operand from one
2813 format to another (e.g., real to integer), the conversion is actually
2814 performed in an internal work area to avoid altering the source operand. A
2815 destination operand may also provide an input to an instruction. It is
2816 distinguished from a source operand, however, because its content may be
2817 altered when it receives the result produced by the operation; that is, the
2818 destination is replaced by the result.
2820 Many instructions allow their operands to be coded in more than one way.
2821 For example, FADD (add real) may be written without operands, with only a
2822 source or with a destination and a source. The instruction descriptions in
2823 this section employ the simple convention of separating alternative operand
2824 forms with slashes; the slashes, however, are not coded. Consecutive
2825 slashes indicate an option of no explicit operands. The operands for FADD
2826 are thus described as
2828 //source/destination, source
2830 This means that FADD may be written in any of three ways:
2832   FADD
2833   FADD source
2834   FADD destination, source
2836 When reading this section, it is important to bear in mind that memory
2837 operands may be coded with any of the CPU's memory addressing modes. To
2838 review these modes‘‘direct, register indirect, based, indexed, based
2839 indexed‘‘refer to the 80286 Programmer's Reference Manual. Table 2-17 later
2840 in this chapter also provides several addressing mode examples.
2843 Data Transfer Instructions
2844 These instructions (summarized in table 2-1) move operands among elements
2845 of the register stack, and between the stack top and memory. Any of the
2846 seven data types can be converted to temporary real and loaded (pushed) onto
2847 the stack in a single operation; they can be stored to memory in the same
2848 manner. The data transfer instructions automatically update the 80287 tag
2849 word to reflect the register contents following the instruction.
2852 FLD source
2853 FLD (load real) loads (pushes) the source operand onto the top of the
2854 register stack. This is done by decrementing the stack pointer by one and
2855 then copying the content of the source to the new stack top. The source may
2856 be a register on the stack (ST(i)) or any of the real data types in memory.
2857 Short and long real source operands are converted to temporary real
2858 automatically. Coding FLD ST(0) duplicates the stack top.
2861 FST destination
2862 FST (store real) transfers the stack top to the destination, which may be
2863 another register on the stack or a short or long real memory operand. If the
2864 destination is short or long real, the significand is rounded to the width
2865 of the destination according to the RC field of the control word, and the
2866 exponent is converted to the width and bias of the destination format.
2868 If, however, the stack top is tagged special (it contains ý, a NaN, or a
2869 denormal) then the stack top's significand is not rounded but is chopped (on
2870 the right) to fit the destination. Neither is the exponent converted, but it
2871 also is chopped on the right and transferred "as is." This preserves the
2872 value's identification as ý or a NaN (exponent all ones) or a denormal
2873 (exponent all zeros) so that it can be properly loaded and tagged later in
2874 the program if desired.
2877 Table 2-1. Data Transfer Instructions
2878 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
2879 �                      Real Transfers                     �
2880 –‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2881 � FLD       �        Load real                            �
2882 � FST       �        Store real                           �
2883 � FSTP      �        Store real and pop                   �
2884 � FXCH      �        Exchange registers                   �
2885 –‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2886 �                     Integer Transfers                   �
2887 –‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2888 � FILD      �        Integer load                         �
2889 � FIST      �        Integer store                        �
2890 � FISTP     �        Integer store and pop                �
2891 –‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2892 �                 Packed Decimal Transfers                �
2893 –‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
2894 � FBLD      �        Packed decimal (BCD) load            �
2895 � FBSTP     �        Packed decimal (BCD) store and pop   �
2896 ”‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
2899 FSTP destination
2900 FSTP (store real and pop) operates identically to FST except that the stack
2901 is popped following the transfer. This is done by tagging the top stack
2902 element empty and then incrementing ST. FSTP permits storing to a temporary
2903 real memory variable, whereas FST does not. Coding FSTP ST(0) is equivalent
2904 to popping the stack with no data transfer.
2907 FXCH//destination
2908 FXCH (exchange registers) swaps the contents of the destination and the
2909 stack top registers. If the destination is not coded explicitly, ST(1) is
2910 used. Many 80287 instructions operate only on the stack top; FXCH provides a
2911 simple means of effectively using these instructions on lower stack
2912 elements. For example, the following sequence takes the square root of the
2913 third register from the top:
2915   FXCH ST(3)
2916   FSQRT
2917   FXCH ST(3)
2920 FILD source
2921 FILD (integer load) converts the source memory operand from its binary
2922 integer format (word, short, or long) to temporary real and loads (pushes)
2923 the result onto the stack. The (new) stack top is tagged zero if all bits in
2924 the source were zero, and is tagged valid otherwise.
2927 FIST destination
2928 FIST (integer store) rounds the content of the stack top to an integer
2929 according to the RC field of the control word and transfers the result to
2930 the destination. The destination may define a word or short integer
2931 variable. Negative zero is stored in the same encoding as positive zero:
2932 0000...00.
2935 FISTP destination
2936 FISTP (integer and pop) operates like FIST and also pops the stack
2937 following the transfer. The destination may be any of the binary integer
2938 data types.
2941 FBLD source
2942 FBLD (packed decimal (BCD) load) converts the content of the source operand
2943 from packed decimal to temporary real and loads (pushes) the result onto the
2944 stack. The sign of the source is preserved, including the case where the
2945 value is negative zero. FBLD is an exact operation; the source is loaded
2946 with no rounding error.
2948 The packed decimal digits of the source are assumed to be in the range
2949 0-9H. The instruction does not check for invalid digits (A-FH) and the
2950 result of attempting to load an invalid encoding is undefined.
2953 FBSTP destination
2954 FBSTP (packed decimal (BCD) store and pop) converts the content of the
2955 stack top to a packed decimal integer, stores the result at the destination
2956 in memory, and pops the stack. FBSTP produces a rounded integer from a
2957 nonintegral value by adding 0.5 to the value and then chopping. Users who
2958 are concerned about rounding may precede FBSTP with FRNDINT.
2961 Arithmetic Instructions
2962 The 80287's arithmetic instruction set (table 2-2) provides a wealth of
2963 variations on the basic add, subtract, multiply, and divide operations, and
2964 a number of other useful functions. These range from a simple absolute value
2965 to a square root instruction that executes faster than ordinary division;
2966 80287 programmers no longer need to spend valuable time eliminating square
2967 roots from algorithms because they run too slowly. Other arithmetic
2968 instructions perform exact modulo division, round real numbers to integers,
2969 and scale values by powers of two.
2971 The 80287's basic arithmetic instructions (addition, subtraction,
2972 multiplication, and division) are designed to encourage the development of
2973 very efficient algorithms. In particular, they allow the programmer to
2974 minimize memory references and to make optimum use of the NPX register
2975 stack.
2977 Table 2-3 summarizes the available operation/operand forms that are
2978 provided for basic arithmetic. In addition to the four normal operations,
2979 two "reversed" instructions make subtraction and division "symmetrical" like
2980 addition and multiplication. The variety of instruction and operand forms
2981 give the programmer unusual flexibility:
2983   Ž  Operands may be located in registers or memory.
2985   Ž  Results may be deposited in a choice of registers.
2987   Ž  Operands may be a variety of NPX data types: temporary real, long
2988      real, short real, short integer or word integer, with automatic
2989      conversion to temporary real performed by the 80287.
2991 Five basic instruction forms may be used across all six operations, as
2992 shown in table 2-3. The classicial stack form may be used to make the 80287
2993 operate like a classical stack machine. No operands are coded in this form,
2994 only the instruction mnemonic. The NPX picks the source operand from the
2995 stack top and the destination from the next stack element. It then pops the
2996 stack, performs the operation, and returns the result to the new stack top,
2997 effectively replacing the operands by the result.
2999 The register form is a generalization of the classical stack form; the
3000 programmer specifies the stack top as one operand and any register on the
3001 stack as the other operand. Coding the stack top as the destination provides
3002 a convenient way to access a constant, held elsewhere in the stack, from
3003 the stack top. The converse coding (ST is the source operand) allows, for
3004 example, adding the top into a register used as an accumulator.
3006 Often the operand in the stack top is needed for one operation but then is
3007 of no further use in the computation. The register pop form can be used to
3008 pick up the stack top as the sourced operand, and then discard it by
3009 popping the stack. Coding operands of ST(1), ST with a register pop
3010 mnemonic is equivalent to a classical stack operation: the top is popped
3011 and the result is left at the new top.
3013 The two memory forms increase the flexibity of the 80287's arithmetic
3014 instructions. They permit a real number or a binary integer in memory to
3015 be used directly as a source operand. This is a very useful facility in
3016 situations where operands are not used frequently enough to justify
3017 holding them in registers. Note that any memory addressing mode may be
3018 used to define these operands, so they may be elements in arrays,
3019 structures, or other data organizations, as well as simple scalars.
3021 The six basic operations are discussed further in the paragraphs following
3022 table 2-3, and descriptions of the remaining seven arithmetic operations
3023 follow.
3025 Table 2-2. Arithmetic Instructions
3027 Addition
3028 FADD                    Add real
3029 FADDP                   Add real and pop
3030 FIADD                   Integer add
3032 Subtraction
3033 FSUB                    Subtract real
3034 FSUBP                   Subtract real and pop
3035 FISUB                   Integer subtract
3036 FSUBR                   Subtract real reversed
3037 FSUBRP                  Subtract real reversed and pop
3038 FISUBR                  Integer subtract reversed
3040 Multiplication
3041 FMUL                    Multiply real
3042 FMULP                   Multiply real and pop
3043 FIMUL                   Integer multiply
3045 Division
3046 FDIV                    Divide real
3047 FDIVP                   Divide real and pop
3048 FIDIV                   Integer divide
3049 FDIVR                   Divide real reversed
3050 FDIVRP                  Divide real reversed and pop
3051 FIDIVR                  Integer divide reversed
3053 Other Operations
3054 FSQRT                   Square root
3055 FSCALE                  Scale
3056 FPREM                   Partial remainder
3057 FRNDINT                 Round to integer
3058 FXTRACT                 Extract exponent and significand
3059 FABS                    Absolute value
3060 FCHS                    Change sign
3063 Table 2-3. Basic Arithmetic Instruction and Operands
3065 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
3066 �  Instruction  � Mnemonic�      Operand Forms         � ASM286 Example�
3067 �     Form      �   Form  �   destination, source      �               �
3068 –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
3069 �Classical stack�   Fop   � {ST(1),ST}                 � FADD          �
3070 �Register       �   Fop   � ST(i),ST or ST,ST(i)       � FSUB  ST,ST(3)�
3071 �Register pop   �   FopP  � ST(i),ST                   � FMULP ST(2),ST�
3072 �Real memory    �   Fop   � {ST,} short-real/long-real � FDIV AZIMUTH  �
3073 �Integer memory �   Flop  � {ST,} word-integer/        � FIDV N_PULSES �
3074 �               �         �       short-integer        �               �
3075 ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
3077 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3078 NOTES
3080   Braces({ }) surround inplicit operands; these are not coded, and
3081   are shown here for information only.
3083   op = ADD  destinaiton \e destination + source
3084        SUB  destination \e destination - source
3085        SUBR destination \e soure - destination
3086        MUL  destination \e destination ¨ source
3087        DIV  destination \e destination ÷ source
3088        DIVR destination \e source ÷ destination
3089 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3092 ADDITION
3093 FADD     //source/destination,source
3094 FADDP    //destination/source
3095 FIADD    source
3097 The addition instructions (add real, add real and pop, integer add) add
3098 the source and destination operands and return the sum to the destination.
3099 The operand at the stack top may be doubled by coding:
3101   FADD ST,ST(0)
3104 NORMAL SUBTRACTION
3105 FSUB   //source/destinaton,source
3106 FSUBP  //destination/source
3107 FISUB  source
3109 The normal subtraction instruction (subtract real,subtract real and pop,
3110 integer subtract) subtract the source operand from the destination and
3111 return the difference to the destination.
3114 REVERSED SUBTRACTION
3115 FSUBR   //source/destinaton,source
3116 FSUBRP  //destination/source
3117 FISUBR  source
3119 The reversed subtraction instructions (subtract real reversed, subtract
3120 real reversed and pop, integer subtract reversed) subtract the destination
3121 from the source and return the difference to the destination.
3124 MULTIPLICATION
3125 FMUL    //source/destination,source
3126 FMULP   destination,source
3127 FIMUL   source
3129 The multiplication instructions (multiply real, multiply real and pop,
3130 integer multiply) multiply the source and destination operands and return
3131 the product to the destination. Coding FMUL ST,ST(0) squares the content
3132 of the stack top.
3135 NORMAL DIVISION
3136 FDIV    //source/destination,source
3137 FDIVP   destination,source
3138 FIDIV   source
3140 The normal division instructions (divide real, divide real and pop,
3141 integer divide) divide the destination by the source and return the
3142 quotient to the destination.
3145 REVERSED DIVISION
3146 FDIVR    //source destination, source
3147 FDIVRP   destination,source
3148 FIDIVR   source
3150 The reversed division instructions (divide real reversed, divide real
3151 reversed and pop, integer divide reversed) divide the source operand by
3152 the destination and return the quotient to the destination.
3155 FSQRT
3156 FSQRT (square root) replaces the content of the top stack element with its
3157 square root. (Note: The square root of -0 is defined to be -0.)
3160 FSCALE
3161 FSCALE (scale) interprets the value contained in ST(1) as an integer and
3162 adds this value to the exponent of the number in ST. This is equivalent to
3164   ST \e ST * 2^(ST(1))
3166 Thus FSCALE provides rapid multiplication or division by integal powers of
3167 2. It is particularly useful for scaling the elements of a vector.
3169 Note that FSCALE assumes the scale factor in ST(1) is an integral value in
3170 the range -2^(15) ¾ x < 2^(15). If the value is not integral, but is
3171 in-range and is greater in magnitude than 1, FSCALE uses the nearest integer
3172 smaller in magnitude; i.e., it chops the value toward 0. If the value is out
3173 of range, or 0 < �x� < 1, the instruction will produce an undefined result
3174 and will not signal an exception. The recommended practice is to load the
3175 scale factor from a word integer to ensure correct operation.
3178 FPREM
3179 FPREM (partial remainder) performs modulo division of the top stack
3180 element by the next stack element, i.e., ST(1) is the modulus. FPREM
3181 produces an exact result; the precision exception does not occur. The sign
3182 of the remainder is the same as the sign of the orginal dividend.
3184 FPREM operates by performing successive scaled subtractions; obtaining the
3185 exact remainder when the operands differ greatly in magnitude can consume
3186 large amounts of execution time. Because the 80287 cas only be preempted
3187 between instructions, the remainder function could seriously increase
3188 interrupt latency in these cases. Accordingly, the instruction is designed
3189 to be executed interactively in a software-controlled loop.
3191 FPREM can reduce a magnitude difference of up to 264 in one execution. If
3192 FPREM produces a remainder that is less than the modulus, the function is
3193 complete and bit C2 of the status word condition code is cleared. If the
3194 function is incomplete, C2 is set to 1; the result is ST is then called
3195 the partial remainder. Software can inspect C2 by storing the status word
3196 following execution of FPREM and re-execute the instruction (using the
3197 partial remainder in ST as the dividend), until C2 is cleared.
3198 Alternatively, a program can determine when the function is complete by
3199 comparing ST to ST(1). If ST > ST(1), then FPREM must be executed again; if
3200 ST = ST(1), then the remainder is 0; if ST < ST(1), then the remainder is
3201 ST. A higher priority interrupting routine that needs the 80287 can force a
3202 context switch between the instructions in the remainder loop.
3204 An important use for FPREM is to reduce arguments (operands) of periodic
3205 transcendental functions to the range permitted by these instructions. For
3206 example, the FPTAN (tangent) instruction requires its argument to be less
3207 than Ò/4. Using Ò/4 as a modulus, FPTAN will reduce an argument so that it
3208 is in range of FPTAN. Because FPREM produces an exact result, the argument
3209 reduction does not introduce roundoff error into the calculation, even if
3210 several iterations are required to bring the argument into range. (The
3211 rounding of Ò does not create the effect of a rounded argument, but of a
3212 rounded period.)
3214 FPREM also provides the least-significant three bits of the quotient
3215 generated by FPREM (in C{3}, C{1}, C{0}). This is also important for
3216 trancendental argument reduction, because it locates the original angle in
3217 the correct one of eight Ò/4 segments of the unit circle (see table 2-4).
3218 If the quotient is less than 4, then C0 will be the value of C3 before
3219 FPREM was executed. If the quotient is less than 2, then C3 will be the
3220 value of C1 before FPREM was executed.
3223 FRNDINT
3224 FRNDINT (round to integer) rounds the top stack element to an integer. For
3225 example, assume that ST contains the 80287 real number encoding of the
3226 decimal value 155.625. FRNDINT will change the value to 155 if the RC field
3227 of the control word is set to down or chop, or to 156 if it is set to up or
3228 nearest.
3231 FXTRACT
3232 FXTRACT (extract exponent and significand) "decomposes" the number in the
3233 stack top into two numbers that represent the actual value of the operand's
3234 exponent and significand fields. The "exponent" replaces the original
3235 operand on the stack and the "significand" is pushed onto the stack.
3236 Following execution of FXTRACT, ST (the new stack top) contains the value of
3237 the original significand expressed as a real number: its sign is the same as
3238 the operand's, its exponent is 0 true (16,383 or 3FFFH biased), and its
3239 significand is identical to the original operand's. ST(1) contains the
3240 value of the original operand's true (unbiased) exponent expressed as a real
3241 number. If the original operand is zero, FXTRACT produces zeros in ST and
3242 ST(1) and both are signed as the original operand.
3244 To clarify the operation of FXTRACT, assume ST contains a number of whose
3245 true exponent is +4 (i.e., its exponent field contains 4003H). After
3246 executing FXTRACT, ST(1) will contain the real number +4.0; its sign will be
3247 positive, its exponent field will contain 4001H (+2 true) and its
3248 significand field will contain 1{\x1e}00...00B. In other words, the value in
3249 ST(1) will be 1.0 * 2^(2) = 4. If ST contains an operand whose true exponent
3250 is -7 (i.e., its exponent field contains 3FF8H), then FXTRACT will return an
3251 "exponent" of -7.0; after the instruction executes, ST(1)'s sign and
3252 exponent fields will contain C001H (negative sign, true exponent of 2), and
3253 its significand will be 1{\x1e}1100...00B. In other words, the value in ST(1)
3254 will be -1.11 * 2^(2) = -7.0. In both cases, following FXTRACT, ST's sign
3255 and significand fields will be the same as the original operand's, and its
3256 exponent field will contain 3FFFH (0 true).
3258 FXTRACT is useful in conjunction with FBSTP for converting numbers in 80287
3259 temporary real format to decimal representations (e.g., for printing or
3260 displaying). It can also be useful for debugging, because it allows the
3261 exponent and significant parts of a real number to be examined separately.
3264 FABS
3265 FABS (absolute value) changes the top stack element to its absolute value
3266 by making its sign positive.
3269 FCHS
3270 FCHS (change sign) complements (reverses) the sign of the top stack
3271 element.
3274 Table 2-4.  Condition Code Interpretation after FPREM
3276 ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
3277 � ’‘‘Condition Code‘‘“                                                �
3278 � C3    C2    C1    C0      Interpretation after FPREM                �
3279 –‘‘‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
3280 �  X  �  1  �  X  �  X  �  Incomplete Reduction;                      �
3281 �     �     �     �     �    further iteration is required for        �
3282 �     �     �     �     �    complete reduction.                      �
3283 �     �     �     �     �  Complete Reduction;                        �
3284 �     �     �     �     �    C1, C3, and C0 contain the three least-  �
3285 �     �     �     �     �    significant bits of quotient:            �
3286 �  0  �  0  �  0  �  0  �  (Quotient) MOD 8 = 0                       �
3287 �  0  �  0  �  0  �  1  �  (Quotient) MOD 8 = 4                       �
3288 �  0  �  0  �  1  �  0  �  (Quotient) MOD 8 = 1                       �
3289 �  0  �  0  �  1  �  1  �  (Quotient) MOD 8 = 5                       �
3290 �  1  �  0  �  0  �  0  �  (Quotient) MOD 8 = 2                       �
3291 �  1  �  0  �  0  �  1  �  (Quotient) MOD 8 = 6                       �
3292 �  1  �  0  �  1  �  0  �  (Quotient) MOD 8 = 3                       �
3293 �  1  �  0  �  1  �  1  �  (Quotient) MOD 8 = 7                       �
3294 ”‘‘‘‘‘™‘‘‘‘‘™‘‘‘‘‘™‘‘‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
3297 Comparison Instructions
3298 Each of these instructions (table 2-5) analyzes the top stack element,
3299 often in relationship to another operand, and reports the result in the
3300 status word condition code. The basic operations are compare, test (compare
3301 with zero), and examine (report tag, sign, and normalization). Special
3302 forms of the compare operation are provided to optimize algorithms by
3303 allowing direct comparisons with binary integers and real numbers in memory,
3304 as well as popping the stack after a comparison.
3306 The FSTSW (store status word) instruction may be used following a
3307 comparison to transfer the condition code to memory for inspection.
3309 Note that instructions other than those in the comparison group may update
3310 the condition code. To ensure that the status word is not altered
3311 inadvertently, store it immediately following a comparison operation.
3314 FCOM //source
3315 FCOM (compare real) compares the stack top to the source operand. The
3316 source operand may be a register on the stack, or a short or long real
3317 memory operand. If an operand is not coded, ST is compared to ST(1).
3318 Positive and negative forms of zero compare identically as if they were
3319 unsigned. Following the instruction, the condition codes reflect the order
3320 of the operands as shown in table 2-6.
3322 NaNs and ý (projective) cannot be compared and return C3 = C0 = 1 as shown
3323 in the table.
3326 FCOMP //source
3327 FCOMP (compare real and pop) operates like FCOM, and in addition pops the
3328 stack.
3331 FCOMPP
3332 FCOMPP (compare real and pop twice) operates like FCOM and additionally
3333 pops the stack twice, discarding both operands. The comparison is of the
3334 stack top to ST(1); no operands may be explicitly coded.
3337 FICOM  source
3338 FICOM (integer compare) converts the source operand, which may reference a
3339 word or short binary integer variable, to temporary real and compares the
3340 stack top to it.
3343 FICOMP source
3344 FICOMP (integer compare and pop) operates identically to FICOM and
3345 additionally discards the value in ST by popping the stack.
3348 FTST
3349 FTST (test) tests the top stack element by comparing it to zero. The result
3350 is posted to the condition codes as shown in table 2-7.
3353 FXAM
3354 FXAM (examine) reports the content of the top stack element as
3355 positive/negative and NaN/unnormal/denormal/normal/zero, or empty.
3356 Table 2-8 lists and interprets all the condition code values that FXAM
3357 generates. Although four different encodings may be returned for an empty
3358 register, bits C3 and C0 of the condition code are both 1 in all encodings.
3359 Bits C2 and C1 should be ignored when examining for empty.
3362 Table 2-5. Comparison Instructions
3364 FCOM                 Compare real
3365 FCOMP                Compare real and pop
3366 FCOMPP               Compare real and pop twice
3367 FICOM                Integer compare
3368 FICOMP               Integer compare and pop
3369 FTST                 Test
3370 FXAM                 Examine
3373 Table 2-6. Condition Code Interpretation after FCOM
3375 ’‘‘ Condition Code ‘‘“
3376 C3    C2     C1     C0     Interpretation after FCOM
3378 0     0      X      0      ST > source
3379 0     0      X      1      ST < source
3380 1     0      X      0      ST = source
3381 1     1      X      1      ST is not comparable
3384 Table 2-7. Condition Code Interpretation after FTST
3386 ’‘‘ Condition Code ‘‘“
3387 C3    C2     C1     C0     Interpretation after FTST
3389 0     0      X      0      ST > 0
3390 0     0      X      1      ST < 0
3391 1     0      X      0      ST = 0
3392 1     1      X      1      ST is not comparable; (i.e., it
3393                            is a NaN or projective infinity)
3396 Table 2-8. FXAM Condition Code Settings
3398 ’‘‘‘ Condition Code ‘‘‘“
3399 C3     C2      C1     C0           Interpretation
3401 0      0       0      0            + Unnormal
3402 0      0       0      1            + NaN
3403 0      0       1      0            - Unnormal
3404 0      0       1      1            - NaN
3405 0      1       0      0            + Normal
3406 0      1       0      1            + ý
3407 0      1       1      0            - Normal
3408 0      1       1      1            - ý
3409 1      0       0      0            + 0
3410 1      0       0      1            Empty
3411 1      0       1      0            - 0
3412 1      0       1      1            Empty
3413 1      1       0      0            + Denormal
3414 1      1       0      1            Empty
3415 1      1       1      0            - Denormal
3416 1      1       1      1            Empty
3419 Transcendental Instructions
3420 The instructions in this group (table 2-9) perform the time-consuming core
3421 calculations for all common trigonometric, inverse trigonometric,
3422 hyperbolic, inverse hyperbolic, logarithmic, and exponential functions.
3423 Prologue and epilogue software may be used to reduce arguments to the range
3424 accepted by the instructions and to adjust the result to correspond to the
3425 original arguments if necessary. The transcendentals operate on the top one
3426 or two stack elements, and they return their results to the stack, also.
3428 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3429 NOTE
3430   The transcendental instructions assume that their operands are valid and
3431   in-range. The instruction descriptions in this section provide the
3432   allowed operand range of each instruction.
3433 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3435 All operands to a transcendental must be normalized; denormals, unnormals,
3436 infinities, and NaNs are considered invalid. (Zero operands are accepted by
3437 some functions and are considered out-of-range by others). If a
3438 transcendental operand is invalid or out-of-range, the instruction will
3439 produce an undefined result without signalling an exception. It is the
3440 programmer's responsibility to ensure that operands are valid and in-range
3441 before executing a transcendental. For periodic functions, FPREM may be
3442 used to bring a valid operand into range.
3445 FPTAN
3446 0 ¾ ST(0) ¾ Ò/4
3448 FPTAN (partial tangent) computes the function Y/X = TAN(Ú). Ú is taken
3449 from the top stack element; it must lie in the range 0 ¾ Ú ¾ Ò/4. The result
3450 of the operation is a ratio; Y replaces Ú in the stack and X is pushed,
3451 becoming the new stack top.
3453 The ratio result of FPTAN and the ratio argument of FPATAN are designed to
3454 optimize the calculation of the other trigonometric functions, including
3455 SIN, COS, ARCSIN, and ARCCOS. These can be derived from TAN and ARCTAN via
3456 standard trigonometric identities.
3459 FPATAN
3460 0 ¾ ST(1) < ST(0) < ý
3462 FPATAN (partial arctangent) computes the function Ú = ARCTAN(Y/X). X is
3463 taken from the top stack element and Y from ST(1). Y and X must observe the
3464 inequality 0 ¾ Y < X < ý. The instruction pops the stack and returns Ú to
3465 the (new) stack top, overwriting the Y operand.
3468 F2XM1
3469 0 ¾ ST(0) ¾ 0.5
3471 F2XM1 (2 to the X minus 1) calculates the function Y = 2^(X) - 1. X is taken
3472 from the stack top and must be in the range 0 ¾ X ¾ 0.5. The result Y
3473 replaces X at the stack top.
3475 This instruction is designed to produce a very accurate result even when X
3476 is close to 0. To obtain Y = 2^(X), add 1 to the result delivered by F2XM1.
3478 The following formulas show how values other than 2 may be raised to a
3479 power of X:
3481   10^(x) = 2^(x * LOG{2}10)
3482    e^(x) = 2^(x * LOG{2}e)
3483    y^(x) = 2^(x * LOG{2}Y)
3485 As shown in the next section, the 80287 has built-in instructions for
3486 loading the constants LOG{2}10 and LOG{2}e, and the FYL2X instruction may be
3487 used to calculate X * LOG{2}Y.
3490 FYL2X
3491 0 < ST(0) < ý - ý < ST(1) < ý
3493 FYL2X (Y log base 2 of X) calculates the function Z = Y * LOG{2}X. X is
3494 taken from the stack top and Y from ST(1). The operands must be in the
3495 ranges 0 < X < ý and -ý < Y < +ý. The instruction pops the stack and returns
3496 Z at the (new) stack top, replacing the Y operand.
3498 This function optimizes the calculations of log to any base other than two,
3499 because a multiplication is always required:
3501   LOG{n}2 * LOG{2}X
3504 FYL2XP1
3505 0 ¾ �ST(0)� < (1 - (¹2/2))
3506 -ý < ST(1) < ý
3508 FYL2XP1 (Y log base 2 of (X + 1)) calculates the function
3509 Z = Y * LOG{2}(X+1). X is taken from the stack top and must be in the range
3510 0 ¾ �X� < (1 - (¹2/2)). Y is taken from ST(1) and must be in the range
3511 -ý < Y < ý. FYL2XP1 pops the stack and returns Z at the (new) stack top,
3512 replacing Y.
3514 The instruction provides improved accuracy over FYL2X when computing the
3515 log of a number very close to 1, for example 1 + ¯ where ¯ << 1. Providing ¯
3516 rather than 1 + ¯ as the input to the function allows more significant
3517 digits to be retained.
3520 Table 2-9. Transcendental Instructions
3522 FPTAN        Partial tangent
3523 FPATAN       Partial arctangent
3524 F2XM1        2^(X) - 1
3525 FYL2X        Y * log{2}X
3526 FYL2XP1      Y * log{2}(X + 1)
3529 Constant Instructions
3530 Each of these instructions (table 2-10) loads (pushes) a commonly-used
3531 constant onto the stack. The values have full temporary real precision (64
3532 bits) and are accurate to approximately 19 decimal digits. Because a
3533 temporary real constant occupies 10 memory bytes, the constant
3534 instructions, which are only two bytes long, save storage and improve
3535 execution speed, in addition to simplifying programming.
3537 FLDZ
3538 FLDZ (load zero) loads (pushes) +0.0 onto the stack.
3540 FLD1
3541 FLD1 (load one) loads (pushes) +1.0 onto the stack.
3543 FLDPI
3544 FLDPI (load Ò) loads (pushes) Ò onto the stack.
3546 FLDL2T
3547 FLDL2T (load log base 2 of 10) loads (pushes) the value LOG{2}10 onto the
3548 stack.
3550 FLDL2E
3551 FLDL2E (load log base 2 of e) loads (pushes) the value LOG{2}e onto the
3552 stack.
3554 FLDLG2
3555 FLDLG2 (load log base 10 of 2) loads (pushes) the value LOG{10}2 onto the
3556 stack.
3558 FLDLN2
3559 FLDLN2 (load log base e of 2) loads (pushes) the value LOG{e}2 onto the
3560 stack.
3563 Table 2-10. Constant Instructions
3565 FLDZ              Load +0.0
3566 FLD1              Load +1.0
3567 FLDPI             Load Ò
3568 FLDL2T            Load log{2}10
3569 FLDL2E            Load log{2}e
3570 FLDLG2            Load log{10}2
3571 FLDLN2            Load log{e}2
3574 Processor Control Instructions
3575 The processor control instructions shown in table 2-11 are not typically
3576 used in calculations; they provide control over the 80287 NPX for
3577 system-level activities. These activities include initialization, exception
3578 handling, and task switching.
3580 As shown in table 2-11, many of the NPX processor control instructions have
3581 two forms of assembler mnemonic:
3583   Ž  A wait form, where the mnemonic is prefixed only with an F, such as
3584      FSTSW. This form checks for unmasked numeric errors.
3586   Ž  A no-wait form, where the mnemonic is prefixed with an FN, such as
3587      FNSTSW. This form ignores unmasked numeric errors.
3589 When the control instruction is coded using the no-wait form of the
3590 mnemonic, the ASM286 assembler does not precede the ESC instruction with a
3591 wait instruction, and the CPU does not test the ERROR status line from the
3592 NPX before executing the processor control instruction.
3594 Only the processor control class of instructions have this alternate
3595 no-wait form. All numeric instructions are automatically synchronized by the
3596 80286, with the CPU testing the BUSY status line and only executing the
3597 numeric instruction when this line is inactive. Because of this automatic
3598 synchronization by the 80286, numeric instructions for the 80287 need not be
3599 preceded by a CPU wait instruction in order to execute correctly.
3601 It should also be noted that the 8087 instructions FENI and FDISI perform
3602 no function in the 80287. If these opcodes are detected in an 80286/80287
3603 instruction stream, the 80287 will perform no specific operation and no
3604 internal states will be affected. For programmers interested in porting
3605 numeric software from 8087 environments to the 80286, however, it should be
3606 noted that program sections containing these exception-handling instructions
3607 are not likely to be completely portable to the 80287. Appendix B contains
3608 a more complete description of the differences between the 80287 and the
3609 8087 NPX.
3612 Table 2-11. Processor Control Instructions
3614 FINIT/FNINIT                  Initialize processor
3615 FSETPM                        Set Protected Mode
3616 FLDCW                         Load control word
3617 FSTCW/FNSTCW                  Store control word
3618 FSTSW/FNSTSW                  Store status word
3619 FSTSW AX/FNSTSW AX            Store status word to AX
3620 FCLEX/FNCLEX                  Clear exceptions
3621 FSTENV/FNSTENV                Store Environment
3622 FLDENV                        Load environment
3623 FSAVE/FNSAVE                  Save state
3624 FRSTOR                        Restore state
3625 FINCSTP                       Increment stack pointer
3626 FDECSTP                       Decrement stack pointer
3627 FFREE                         Free register
3628 FNOP                          No operation
3629 FWAIT                         CPU Wait
3632 FINIT/FNINIT
3633 FINIT/FNINIT (initialize processor) sets the 80287 NPX into a known state,
3634 unaffected by any previous activity. The no-wait form of this instruction
3635 will cause the 80287 to abort any previous numeric operations currently
3636 executing in the NEU. This instruction performs the functional equivalent
3637 of a hardware RESET, with one exception; FINIT/FNINIT does not affect the
3638 current 80287 operating mode (either Real-Address mode or Protected mode).
3639 FINIT checks for unmasked numeric exceptions, FNINIT does not.
3641 Note that if FNINIT is executed while a previous 80287 memory-referencing
3642 instruction is running, 80287 bus cycles in progress will be aborted. This
3643 instruction may be necessary to clear the 80287 if a Processor Extension
3644 Segment Overrun Exception (Interrupt 9) is detected by the CPU.
3647 FSETPM
3648 FSETPM (set Protected mode) sets the operating mode of the 80287 to
3649 Protected Virtual-Address mode. When the 80287 is first initialized
3650 following hardware RESET, it operates in Real-Address mode, just as does the
3651 80286 CPU. Once the 80287 NPX has been set into Protected mode, only a
3652 hardware RESET can return the NPX to operation in Real-Address mode.
3654 When the 80287 operates in Protected mode, the NPX exception pointers are
3655 represented differently than they are in Real-Address mode (see the FSAVE
3656 and FSTENV instructions that follow). This distinction is evident primarily
3657 to writers of numeric exception handlers, however. For general application
3658 programmers, the operating mode of the 80287 need not be a concern.
3661 FLDCW source
3662 FLDCW (load control word) replaces the current processor control word with
3663 the word defined by the source operand. This instruction is typically used
3664 to establish or change the 80287's mode of operation. Note that if an
3665 exception bit in the status word is set, loading a new control word that
3666 unmasks that exception and clears the interrupt enable mask will generate an
3667 immediate interrupt request before the next instruction is executed. When
3668 changing modes, the recommended procedure is to first clear any exceptions
3669 and then load the new control word.
3672 FSTCW/FNSTCW destination
3673 FSTCW/FNSTCW (store control word) writes the current processor control word
3674 to the memory location defined by the destination. FSTCW checks for unmasked
3675 numeric exceptions, FNSTCW does not.
3678 FSTSW/FNSTSW destination
3679 FSTSW/FNSTCW (store status word) writes the current value of the 80287
3680 status word to the destination operand in memory. The instruction is used to
3682   Ž  Implement conditional branching following a comparison or FPREM
3683      instruction (FSTSW)
3685   Ž  Poll the 80287 to determine if it is busy (FNSTSW)
3687   Ž  Invoke exception handlers in environments that do not use interrupts
3688      (FSTSW).
3690 FSTSW checks for unmasked numeric exceptions, FNSTSW does not.
3693 FSTSW AX/FNSTSW AX
3694 FSTSW AX/FNSTSW AX (store status word to AX) is a special 80287 instruction
3695 that writes the current value of the 80287 status word directly into the
3696 80286 AX register. This instruction optimizes conditional branching in
3697 numeric programs, where the 80286 CPU must test the condition of various NPX
3698 status bits. The waited form checks for unmasked numeric exceptions, the
3699 non-waited for does not.
3701 When this instruction is executed, the 80286 AX register is updated with
3702 the NPX status word before the CPU executes any further instructions. In
3703 this way, the 80286 can immediately test the NPX status word without any
3704 WAIT or other synchronization instructions required.
3707 FCLEX/FNCLEX
3708 FCLEX/FNCLEX (clear exceptions) clears all exception flags, the error
3709 status flag and the busy flag in the status word. As a consequence, the
3710 80287's ERROR line goes inactive. FCLEX checks for unmasked numeric
3711 exceptions, FNCLEX does not.
3714 FSAVE/FNSAVE destination
3715 FSAVE/FNSAVE (save state) writes the full 80287 state‘‘environment plus
3716 register stack‘‘to the memory location defined by the destination operand.
3717 Figure 2-1 shows the layout of the 94-byte save area; typically the
3718 instruction will be coded to save this image on the CPU stack. FNSAVE
3719 delays its execution until all NPX activity completes normally. Thus, the
3720 save image reflects the state of the NPX following the completion of any
3721 running instruction. After writing the state image to memory, FSAVE/FNSAVE
3722 initializes the 80287 as if FINIT/FNINIT had been executed.
3724 FSAVE/FNSAVE is useful whenever a program wants to save the current state
3725 of the NPX and initialize it for a new routine. Three examples are
3727   Ž  An operating system needs to perform a context switch (suspend the
3728      task that had been running and give control to a new task).
3730   Ž  An exception handler needs to use the 80287.
3732   Ž  An application task wants to pass a "clean" 80287 to a subroutine.
3734 FSAVE checks for unmasked numeric errors before executing, FNSAVE does not.
3735 An FWAIT should be executed before CPU interrupts are enabled or any
3736 subsequent 80287 instruction is executed. Other CPU instructions may be
3737 executed between the FNSAVE/FSAVE and the FWAIT.
3740 Figure 2-1.  FSAVE/FRSTOR Memory Layout
3742                                            \x11‘‘‘‘‘‘‘‘‘‘‘‘“INCREASING
3743                         ‚�������������������������ƒ     �ADDRESS
3744         REAL MODE       €      CONTROL WORD       € +0  �
3745                         Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘     �
3746                         €       STATUS WORD       € +2  �
3747                         Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘     \x1f
3748                         €        TAG WORD         € +4
3749                         Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3750                       ’‘€INSTRUCTION POINTER(15-0)€ +6
3751                       � Ã‘‘‘‘‘‘‘‘‘‘‘˜‘˜‘‘‘‘‘‘‘‘‘‘‘Â
3752            INSTRUCTION� €INSTRUCTION� �INSTRUCTION€
3753                POINTER— €  POINTER  �0�  OPCODE   € +8
3754                       � €  (19-14)  � �  (10-0)   €
3755                       ã�Ñ‘‘‘‘‘‘‘‘‘‘™‘™‘‘‘‘‘‘‘‘‘‘‘Â
3756                OPERAND� €   DATA POINTER(15-0)    € +10
3757                POINTER— Ã‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3758                       � €   DATA    �             €
3759                       ”‘€  POINTER  �      0      € +12
3760                         €  (19-16)  �             €
3761                         „��ˆ��������¤����������ˆ��…
3762                          ’‘€ SIGNIFICAND 15-0  € +14
3763                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3764                          � € SIGNIFICAND 31-16 € +16
3765                 TOP STACK— Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3766                ELEMENT:ST� € SIGNIFICAND 47-32 € +18
3767                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3768                          � € SIGNIFICAND 63-48 € +20
3769                          � Ã‘\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3770                          ”‘€S�  EXPONENT 14-0  € +22
3771                            Ã‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3772                          ’‘€ SIGNIFICAND 15-0  € +14
3773                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3774                          � € SIGNIFICAND 31-16 € +16
3775                NEXT STACK— Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3776             ELEMENT:ST(1)� € SIGNIFICAND 47-32 € +18
3777                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3778                          � € SIGNIFICAND 63-48 € +20
3779                          � Ã‘\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3780                          ”‘€S�  EXPONENT 14-0  € +22
3781                            Ã‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3782                            Ã‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3783                            ¸                   ¸
3784                            Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3785                          ’‘€ SIGNIFICAND 15-0  € +84
3786                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3787                          � € SIGNIFICAND 31-16 € +86
3788                LAST STACK— Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3789             ELEMENT:ST(7)� € SIGNIFICAND 47-32 € +88
3790                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3791                          � € SIGNIFICAND 63-48 € +90
3792                          � Ã‘\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3793                          ”‘€S�  EXPONENT 14-0  € +92
3794                            „�¤�����������������…
3797                                           \x11‘‘‘‘‘‘‘‘‘‘‘‘“INCREASING
3798                                                        �ADDRESSES
3799                           ‚���������������������ƒ      �
3800         PROTECTED MODE    €    CONTROL WORD     € +0   �
3801                           Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘      �
3802                           €     STATUS WORD     € +2   �
3803                           Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘      \x1f
3804                           €      TAG WORD       € +4
3805                           Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3806                           €      IP OFFSET      € +6
3807                           Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3808                           €     CS SELECTOR     € +8
3809                           Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3810                           € DATA OPERAND OFFSET € +10
3811                           Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3812                           €DATA OPERAND SELECTOR€ +12
3813                           „ˆ�������������������ˆ…
3814                          ’‘€ SIGNIFICAND 15-0  € +14
3815                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3816                          � € SIGNIFICAND 31-16 € +16
3817                 TOP STACK— Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3818                ELEMENT:ST� € SIGNIFICAND 47-32 € +18
3819                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3820                          � € SIGNIFICAND 63-48 € +20
3821                          � Ã‘\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3822                          ”‘€S�  EXPONENT 14-0  € +22
3823                            Ã‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3824                          ’‘€ SIGNIFICAND 15-0  € +24
3825                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3826                          � € SIGNIFICAND 31-16 € +26
3827                NEXT STACK— Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3828             ELEMENT:ST(1)� € SIGNIFICAND 47-32 € +28
3829                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3830                          � € SIGNIFICAND 63-48 € +30
3831                          � Ã‘\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3832                          ”‘€S�  EXPONENT 14-0  € +32
3833                            Ã‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3834                            ¸                   ¸
3835                            Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3836                            € SIGNIFICAND 15-0  € +84
3837                          ’‘Ñ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3838                          � € SIGNIFICAND 31-16 € +86
3839                          � Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3840                LAST STACK— € SIGNIFICAND 47-32 € +88
3841             ELEMENT:ST(7)� Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3842                          � € SIGNIFICAND 63-48 € +90
3843                          � Ã‘\x1e‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3844                          � €S�  EXPONENT 14-0  € +92
3845                          ”‘„�¤�����������������…
3847 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3848 NOTES:
3849   a = INSTRUCTION POINTER
3850   b = OPERAND POINTER
3851   S = Sign
3852   Bit 0 of each field is rightmost, least significant
3853         bit of corresponding register field.
3854   Bit 63 of significand is integer bit (assumed
3855         binary point is immediately to the right.)
3856 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3859 FRSTOR source
3860 FRSTOR (restore state) reloads the 80287 from the 94-byte memory area
3861 defined by the source operand. This information should have been written by
3862 a previous FSAVE/FNSAVE instruction and not altered by any other
3863 instruction. An FWAIT is not required after FRSTOR. FRSTOR will
3864 automatically wait and check for interrupts until all data transfers are
3865 completed before continuing to the next instruction.
3867 Note that the 80287 "reacts" to its new state at the conclusion of the
3868 FRSTOR; it will, for example, generate an exception request if the exception
3869 and mask bits in the memory image so indicate when the next WAIT or
3870 error-checking-ESC instruction is executed.
3873 FSTENV/FNSTENV destination
3874 FSTENV/FNSTENV (store environment) writes the 80287's basic
3875 status‘‘control, status, and tag words, and exception pointers‘‘to the
3876 memory location defined by the destination operand. Typically, the
3877 environment is saved on the CPU stack. FSTENV/FNSTENV is often used by
3878 exception handlers because it provides access to the exception pointers that
3879 identify the offending instruction and operand. After saving the
3880 environment, FSTENV/FNSTENV sets all exception masks in the processor.
3881 FSTENV checks for pending errors before executing, FNSTENV does not.
3883 Figure 2-2 shows the format of the environment data in memory. FNSTENV does
3884 not store the environment until all NPX activity has completed. Thus, the
3885 data saved by the instruction reflects the 80287 after any previously
3886 decoded instruction has been executed. After writing the environment image
3887 to memory, FNSTENV/FSTENV initializes the 80287 state as if FNINIT/FINIT
3888 had been executed.
3890 FSTENV/FNSTENV must be allowed to complete before any other 80287
3891 instruction is decoded. When FSTENV is coded, an explicit FWAIT, or
3892 assembler-generated WAIT, should precede any subsequent 80287 instruction.
3895 Figure 2-2.  FSTENV/FLDENV Memory Layout
3897             REAL MODE                            PROTECTED MODE
3898   15                            0 MEMORY  15                        0 MEMORY
3899  ‚�������������������������������ƒOFFSET ‚���������������������������ƒOFFSET
3900  €         CONTROL WORD          € +0    €       CONTROL WORD        € +0
3901  Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3902  €          STATUS WORD          € +2    €        STATUS WORD        € +2
3903  Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3904  €           TAG WORD            € +4    €         TAG WORD          € +4
3905  Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3906  €   INSTRUCTION POINTER(15-0)   € +6    €         IP OFFSET         € +6
3907  Ã‘‘‘‘‘‘‘‘‘‘‘˜‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3908  €INSTRUCTION� �   INSTRUCTION   €       €                           €
3909  €  POINTER  �0�     OPCODE      € +8    €        CS SELECTOR        € +8
3910  €  (19-14)  � �     (10-0)      €       €                           €
3911  Ã‘‘‘‘‘‘‘‘‘‘‘™‘™‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3912  €      DATA POINTER(15-0)       € +10   €    DATA OPERAND OFFSET    € +10
3913  Ã‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘       Ã‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘Â
3914  €   DATA    �                   €       €                           €
3915  €  POINTER  �         0         € +12   €   DATA OPERAND SELECTOR   € +12
3916  €  (19-16)  �                   €       €                           €
3917  „�����������¤�������������������…       „���������������������������…
3918   15       12 11                0
3921 FLDENV source
3922 FLDENV (load environment) reloads the environment from the memory area
3923 defined by the source operand. This data should have been written by a
3924 previous FSTENV/FNSTENV instruction. CPU instructions (that do not reference
3925 the environment image) may immediately follow FLDENV. An FWAIT is not
3926 required after FLDENV. FLDENV will automatically wait for all data
3927 transfers to complete before executing the next instruction.
3929 Note that loading an environment image that contains an unmasked exception
3930 will cause a numeric exception when the next WAIT or error-checking-ESC
3931 instruction is executed.
3934 FINCSTP
3935 FINCSTP (increment stack pointer) adds 1 to the stack top pointer (ST) in
3936 the status word. It does not alter tags or register contents, nor does it
3937 transfer data. It is not equivalent to popping the stack, because it does
3938 not set the tag of the previous stack top to empty. Incrementing the stack
3939 pointer when ST = 7 produces ST = 0.
3942 FDECSTP
3943 FDECSTP (decrement stack pointer) subtracts 1 from ST, the stack top
3944 pointer in the status word. No tags or registers are altered, nor is any
3945 data transferred. Executing FDECSTP when ST = 0 produces ST = 7.
3948 FFREE destination
3949 FFREE (free register) changes the destination register's tag to empty; the
3950 content of the register is unaffected.
3953 FNOP
3954 FNOP (no operation) stores the stack top to the stack top (FST ST,ST(0))
3955 and thus effectively performs no operation.
3958 FWAIT (CPU Instruction)
3959 FWAIT is not actually an 80287 instruction, but an alternate mnemonic for
3960 the CPU WAIT instruction. The FWAIT or WAIT mnemonic should be coded
3961 whenever the programmer wants to synchronize the CPU to the NPX, that is, to
3962 suspend further instruction decoding until the NPX has completed the current
3963 instruction. FWAIT will check for unmasked numeric exceptions.
3965 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3966 NOTE
3967   A CPU instruction should not attempt to access a memory operand until the
3968   80287 instruction has completed. For example, the following coding shows
3969   how FWAIT can be used to force the CPU instruction to wait for the 80287:
3971      FIST     VALUE
3972      FWAIT    ; Wait for FIST to complete
3973      MOV      AX,VALUE
3974 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
3976 More information on when to code an FWAIT instruction is given in a
3977 following section of this chapter, "Concurrent Processing with the 80287."
3980 Instruction Set Reference Information
3981 Table 2-14 later in this chapter lists the operating characteristics of all
3982 the 80287 instructions. There is one table entry for each instruction
3983 mnemonic; the entries are in alphabetical order for quick lookup. Each entry
3984 provides the general operand forms accepted by the instruction as well as a
3985 list of all exceptions that may be detected during the operation.
3987 One entry exists for each combination of operand types that can be coded
3988 with the mnemonic. Table 2-12 explains the operand identifiers allowed in
3989 table 2-14. Following this entry are columns that provide execution time in
3990 clocks, the number of bus transfers run during the operation, the length of
3991 the instruction in bytes, and an ASM286 coding sample.
3994 Instruction Execution Time
3995 The execution of an 80287 instruction involves three principal activities,
3996 each of which may contribute to the overall execution time of the
3997 instruction:
3999   Ž  80286 CPU overhead involved in handling the ESC instruction opcode
4000      and setting up the 80287 NPX
4002   Ž  Instruction execution by the 80287 NPX
4004   Ž  Operand transfers between the 80287 NPX and memory or a CPU register
4006 The timing of these various activities is affected by the individual clock
4007 frequencies of the 80286 CPU and the 80287 NPX. In addition, slow memories
4008 requiring the insertion of wait states in bus cycles, and bus contention due
4009 to other processors in the system, may lengthen operand transfer times.
4011 In calculating an overall execution time for an individual numeric
4012 instruction, analysts must take each of these activities into account. In
4013 most cases, it can be assumed that the numeric instructions have already
4014 been prefetched by the 80286 and are awaiting execution.
4016   Ž  The CPU overhead in handling the ESC instruction opcode takes only a
4017      single CPU bus cycle before the 80287 begins its execution of the
4018      numeric instruction. The timing of this bus cycle is determined by the
4019      CPU clock. Additional CPU activity is required to set up the 80287's
4020      instruction and data pointer registers, but this activity occurs after
4021      the 80287 has begun executing its instruction, and so this parallel
4022      activity does not affect total execution time.
4024   Ž  The duration of individual numeric instructions executing on the 80287
4025      varies for each instruction. Table 2-14 quotes a typical execution
4026      clock count and a range for each 80287 instruction. Dividing the
4027      figures in the table by 10 (for a 10-MHz 80287 NPX clock) produces an
4028      execution time in microseconds. The typical case is an estimate for
4029      operand values that normally characterize most applications. The range
4030      encompasses best- and worst-case operand values that may be found in
4031      extreme circumstances.
4033   Ž  The operand transfer time required to transfer operands between the
4034      80287 and memory or a CPU register depends on the number of words to be
4035      transferred, the frequency of the CPU clock controlling bus timing, the
4036      number of wait states added to accommodate slower memories, and
4037      whether operands are based at even or odd memory addresses. Some
4038      (small) additional number of bus cycles may also be lost due to the
4039      asynchronous nature of the PEREQ/PEACK handshaking between the 80286
4040      and 80287, and this interaction varies with relative frequencies of
4041      the CPU and NPX clocks.
4043 The execution clock counts for the NPX execution of instructions shown in
4044 table 2-14 assume that no exceptions are detected during execution. Invalid
4045 operation, denormalized operand (unmasked), and zero divide exceptions
4046 usually decrease execution time from the typical figure, but execution
4047 still falls within the indicated range. The precision exception has no
4048 effect on execution time. Unmasked overflow and underflow, and masked
4049 denormalized exceptions impose additional execution penalties as shown in
4050 table 2-13. Absolute worst-case execution times are therefore the high
4051 range figure plus the largest penalty that may be encountered.
4054 Table 2-12. Key to Operand Types
4057 Identifier      Explanation
4059 ST              Stack top; the register currently at the top of the stack.
4061 ST(i)           A register in the stack i (0¾i¾7) stack elements from the
4062                 top. ST(1) is the next-on-stack register, ST(2) is below
4063                 ST(1), etc.
4065 Short-real      A short real (32 bits) number in memory.
4067 Long-real       A long real (64 bits) number in memory.
4069 Temp-real       A temporary real (80 bits) number in memory.
4071 Packed-decimal  A packed decimal integer (18 digits, 10 bytes) in memory.
4073 Word-integer    A word binary integer (16 bits) in memory.
4075 Short-integer   A short binary integer (32 bits) in memory.
4077 Long-integer    A long binary integer (64 bits) in memory.
4079 nn-bytes        A memory area nn bytes long.
4082 Bus Transfers
4083 NPX instructions that reference memory require bus cycles to transfer
4084 operands between the NPX and memory. The actual number of transfers depends
4085 on the length of the operand and the alignment of the operand in memory.
4086 In table 2-14, the first figure gives execution clocks for even-addressed
4087 operands, while the second gives the clock count for odd-addressed operands.
4089 For operands aligned at word boundaries, that is, based at even memory
4090 addresses, each word to be transferred requires one bus cycle between the
4091 80286 data channel and memory, and one bus cycle to the NPX. For operands
4092 based at odd memory addresses, each word transfer requires two bus cycles
4093 to transfer individual bytes between the 80286 data channel and memory, and
4094 one bus cycle to the NPX.
4096 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4097 NOTE
4098   For best performance, operands for the 80287 should be aligned along word
4099   boundaries; that is, based at even memory addresses. Operands based at odd
4100   memory addresses are transferred to memory essentially byte-at-a-time and
4101   may take half again as long to transfer as word-aligned operands.
4102 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4104 Additional transfer time is required if slow memories are being used,
4105 requiring the insertion of wait states into the CPU bus cycle. In
4106 multiprocessor environments, the bus may not be available immediately; this
4107 overhead can also increase effective transfer time.
4110 Table 2-13. Execution Penalties
4112 Exception                 Additional Clocks
4113 Overflow (unmasked)              14
4114 Underflow (unmasked)             16
4115 Denormalized (masked)            33
4118 Instruction Length
4119 80287 instructions that do not reference memory are two bytes long. Memory
4120 reference instructions vary between two and four bytes. The third and fourth
4121 bytes are for the 8- or 16-bit displacement values used in conjunction with
4122 the standard 80286 memory-addressing modes.
4124 Note that the lengths quoted in table 2-14 for the processor control
4125 instructions (FNINIT, FNSTCW, FNSTSW, FNSTSW AX, FNCLEX, FNSTENV, and
4126 FNSAVE) do not include the one-byte CPU wait instruction inserted by the
4127 ASM286 assembler if the control instruction is coded using the wait form of
4128 the mnemonic (e.g. FINIT, FSTCW, FSTSW, FSTSW AX, FCLEX, FSTENV, and
4129 FSAVE). Wait and no-wait forms of the processor control instructions have
4130 been described in the preceding section titled "Processor Control
4131 Instructions."
4134 Table 2-14. Instruction Set Reference Data
4137                      ®Execution Clocks¬     Operand Word    Code
4138 Operands              Typical    Range       Transfers      Bytes   Coding Example
4139 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4140 FABS                  FABS (no operands)
4141                       Absolute value                        Exceptions: I
4143 (no operands)         14         10-17          0           2       FABS
4144 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4145 FADD                  FADD\\source\destination,source
4146                       Add real                              Execptions: I,D,O,U,P
4148 \\ST,ST(i)\ST(i),ST   85         70-100         0           2       FADD,ST,ST(4)
4149 short-real            105        90-120         2           2-4     FADD AIR_TEMP [SI]
4150 long-real             110        95-125         4           2-4     FADD [BX].MEAN
4151 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4152 FADDP                 FADDP destination, source
4153                       Add real and pop                      Exceptions: I,D,O,U,P
4155 ST(i),ST              90         75-105         0           2       FADDP ST(2),ST
4156 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4157 FBLD                  FBLD source
4158                       Packed decimal (BCD) load             Exceptions: I
4160 packed-decimal        300        290-310        5           2-4     FBLD YTD_SALES
4161 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4162 FBSTP                 FBSTP destination
4163                       Packed decimal (BCD) store and pop    Exceptions: I
4165 packed-decimal        530        520-540        5           2-4     FBSTP [BX].FORECAST
4166 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4167 FCHS                  FCHS (no operands)
4168                       Change sign                           Exceptions: I
4169 (no operands)         15         10-17          0           2       FCHS
4170 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4171 FCLEX/FNCLEX          FCLEX/FNCLEX(no operands)
4172                       Clear exceptions                      Exceptions: None
4174 (no operands)         5          2-8            0           2       FNCLEX
4175 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4176 FCOM                  FCOM //source
4177                       Compare real                          Exceptions: I, D
4179 //ST(i)               45         40-50          0           2       FCOM ST(1)
4180 short-real            65         60-70          2           2-4     FCOM [BP].UPPER_LIMIT
4181 long-real             70         65-75          4           2-4     FCOM WAVELENGTH
4182 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4183 FCOMP                 FCOMP //source
4184                       Compare real and pop                  Exceptions: I, D
4186 //ST(i)               47         42-52          0           2       FCOMP ST(2)
4187 short-real            68         63-73          2           2-4     FCOMP [BP + 2].N_READINGS
4188 long-real             72         67-77          4           2-4     FCOMP DENSITY
4189 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4190 FCOMPP                FCOMPP (no operands)
4191                       Compare real and pop twice                    Exceptions: I, D
4193 (no operands)         50         45-55          0           2       FCOMPP
4194 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4195 FDECSTP               FDECSTP (no operands)
4196                       Decrement stack pointer               Exceptions: None
4198 (no operands)         9          6-12           0           2       FDECSTP
4199 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4200 FDIV                  FDIV //source/destination,source
4201                       Divide real                           Exceptions: I, D, Z, O, U, P
4203 //ST(i),ST            198        193-203        0           2       FDIV
4204 short-real            220        215-225        2           2-4     FDIV DISTANCE
4205 long-real             225        220-230        4           2-4     FDIV ARC [DI]
4206 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4207 FDIVP                 FDIVP destination, source
4208                       Divide real and pop                   Exceptions: I, D, Z, O, U, P
4210 ST(i),ST              202        197-207        0           2       FDIVP ST(4),ST
4211 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4212 FDIVR                 FDIVR //source/destination, source
4213                       Divide real reversed                  Exceptions: I, D, Z, O, U, P
4215 //ST,ST(i)/ST(i),ST   199        194-204        0           2       FDIVR ST(2),ST
4216 short-real            221        216-226        2           2-4     FDIVR [BX].PULSE_RATE
4217 long-real             226        221-231        4           2-4     FDIVR RECORDER.FREQUENCY
4218 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4219 FDIVRP                FDIVRP destination, source
4220                       Divide real reversed and pop          Exceptions: I, D, Z, O, U, P
4222 ST(i),ST              203        198-208        0           2       FDIVRP ST(1),ST
4223 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4224 FFREE                 FFREE destination
4225                       Free register                         Exceptions: None
4227 ST(i)                 11         9-16           0           2       FFREE ST(1)
4228 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4229 FIADD                 FIADD source
4230                       Integer add                           Exceptions: I, D, O, P
4232 word-integer          120        102-137        1           2-4     FIADD DISTANCE_TRAVELLED
4233 short-integer         125        108-143        2           2-4     FIADD PULSE_COUNT [SI]
4234 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4235 FICOM                 FICOM source
4236                       Integer compare                       Exceptions: I, D
4238 word-integer          80         72-86          1           2-4     FICOM TOOL.N_PASSES
4239 short-integer         85         78-91          2           2-4     FICOM [BP+4].PARM_COUNT
4240 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4241 FICOMP                FICOMP source
4242                       Integer compare and pop               Exceptions: I, D
4244 word-integer          82         74-88          1           2-4     FICOMP [BP].LIMIT [SI]
4245 short-integer         87         80-93          2           2-4     FICOMP N_SAMPLES
4246 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4247 FIDIV                 FIDIV source
4248                       Integer divide                        Exceptions: I, D, Z, O, U, P
4250 word-integer          230        224-238        1           2-4     FIDIV SURVEY.OBSERVATIONS
4251 short-integer         236        230-243        2           2-4     FIDIV RELATIVE_ANGLE [DI]
4252 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4253 FIDIVR                FIDIVR source
4254                       Integer divide reversed               Exceptions: I, D, Z, O, U, P
4256 word-integer          230        225-239        1           2-4     FIDIVR [BP].X_COORD
4257 short-integer         237        231-245        2           2-4     FIDIVR FREQUENCY
4258 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4259 FILD                  FILD source
4260                       Integer load                          Exceptions: I
4262 word-integer          50         46-54          1           2-4     FILD [BX].SEQUENCE
4263 short-integer         56         52-60          2           2-4     FILD STANDOFF [DI]
4264 long-integer          64         60-68          4           2-4     FILD RESPONSE.COUNT
4265 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4266 FIMUL                 FIMUL source
4267                       Integer multiply                      Exceptions: I, D, O, P
4269 word-integer          130        124-138        1           2-4     FIMUL BEARING
4270 short-integer         136        130-144        2           2-4     FIMUL POSITION.Z_AXIS
4271 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4272 FINCSTP               FINCSTP (no operands)
4273                       Increment stack pointer               Exceptions: None
4275 (no operands)         9          6-12           0           2       FINCSTP
4276 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4277 FINIT/FNINIT          FINIT/FNINIT (no operands)
4278                       Initialize processor                  Exceptions: None
4280 (no operands)         5          2-8            0           2       FINIT
4281 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4282 FIST                  FIST destination
4283                       Integer store                         Exceptions: I, P
4285 word-integer          86         80-90          1           2-4     FIST OBS.COUNT[SI]
4286 short-integer         88         82-92          2           2-4     FIST [BP;].FACTORED_PULSES
4287 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4288 FISTP                 FISTP destination
4289                       Integer store and pop                 Exceptions: I, P
4291 word-integer          88         82-92          1           2-4     FISTP [BX].ALPHA_COUNT [SI]
4292 short-integer         90         84-94          2           2-4     FISTP CORRECTED_TIME
4293 long-integer          100        94-105         4           2-4     FISTP PANEL.N_READINGS
4294 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4295 FISUB                 FISUB source
4296                       Integer subtract                      Exceptions: I, D, O, P
4298 word-integer          120        102-137        1           2-4     FISUB BASE_FREQUENCY
4299 short-integer         125        108-143        2           2-4     FISUB TRAIN_SIZE [DI]
4300 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4301 FISUBR                FISUBR source
4302                       Integer subtract reversed             Exceptions: I, D, O, P
4304 word-integer          120        103-139        1           2-4     FISUBR FLOOR [BX] [SI]
4305 short-integer         125        109-144        2           2-4     FISUBR BALANCE
4306 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4307 FLD                   FLD source
4308                       Load real                             Exceptions: I, D
4310 ST(i)                 20         17-22          0           2       FLD ST(0)
4311 short-real            43         38-56          2           2-4     FLD READING [SI].PRESSURE
4312 long-real             46         40-60          4           2-4     FLD BP].TEMPERATURE
4313 temp-real             57         53-65          5           2-4     FLD SAVEREADING
4314 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4315 FLDCW                 FLDCW source
4316                       Load control word                     Exceptions: None
4318 2-bytes               10         7-14           1           2-4     FLDCW CONTROL_WORD
4319 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4320 FLDENV                FLDENV source
4321                       Load environment                      Exceptions: None
4323 14-bytes              40         35-45          7           2-4     FLDENV [BP + 6]
4324 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4325 FLDLG2                FLDLG2 (no operands)
4326                       Load log{10}2                         Exceptions: I
4328 (no operands)         21         18-24          0           2       FLDLG2
4329 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4330 FLDLN2                FLDLN2 (no operands)
4331                       Load log{e}2                          Exceptions: I
4333 (no operands)         20         17-23          0           2       FLDLN2
4334 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4335 FLDL2E                FLDL2E (no operands)
4336                       Load log{2}e                          Exceptions: I
4338 (no operands)         18         15-21          0           2       FLDL2E
4339 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4340 FLDL2T                FLDL2T (no operands)
4341                       Load log{2}10                         Exceptions: I
4343 (no operands)         19         16-22          0           2       FLDL2T
4344 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4345 FLDPI                 FLDPI (no operands)
4346                       Load Ò                                Exceptions: I
4348 (no operands)         19         16-22          0           2       FLDPI
4349 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4350 FLDZ                  FLDZ (no operands)
4351                       Load +0.0                             Exceptions: I
4353 (no operands)         14         11-17          0           2       FLDZ
4354 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4355 FLD1                  FLD1 (no operands)
4356                       Load +1.0                             Exceptions: I
4358 (no operands)         18         15-21          0           2       FLD1
4359 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4360 FMUL                  FMUL //source/destination,source
4361                       Multiply real                         Exceptions: I, D, O, U, P
4363 //ST(i),ST/T,ST(i)
4364 Occurs when one or both operands is "short"‘‘it has 40 trailing zeros
4365 in its fraction (e.g., it was loaded from a short-real memory operand).    97         90-105        0           2       FMUL ST,ST(3)
4366 //ST(i),ST/ST,ST(i)   138        130-145        0           2       FMUL ST,ST(3)
4367 short-real            118        110-125        2           2-4     FMUL SPEED_FACTOR
4368 long-real
4369 Occurs when one or both operands is "short"‘‘it has 40 trailing zeros
4370 in its fraction (e.g., it was loaded from a short-real memory operand).            120        112-126        4           2-4     FMUL [BP].HEIGHT
4371 long-real             161        154-168        4           2-4     FMUL [BP].HEIGHT
4372 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4373 FMULP                 FMULP destination, source
4374                       Multiply real and pop                 Exceptions: I, D, O, U, P
4376 ST(i),ST
4377 Occurs when one or both operands is "short"‘‘it has 40 trailing zeros
4378 in its fraction (e.g., it was loaded from a short-real memory operand).             100        94-108         0           2       FMULP ST(1),ST
4379 ST(i),ST              142        134-148        0           2       FMULP ST(1),ST
4380 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4381 FNOP                  FNOP (no operands)
4382                       No operation                          Exceptions: None
4384 (no operands)         13         10-16          0           2       FNOP
4385 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4386 FPATAN                FPATAN (no operands)
4387                       Partial arctangent                    Exceptions: U, P (operands not checked)
4389 (no operands)         650        250-800        0           2       FPATAN
4390 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4391 FPREM                 FPREM (no operands)
4392                       Partial remainder                     Exceptions: I, D, U
4394 (no operands)         125        15-190         0           2       FPREM
4395 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4396 FPTAN                 FPTAN (no operands)
4397                       Partial tangent                       Exceptions: I, P (operands not checked)
4399 (no operands)         450        30-540         0           2       FPTAN
4400 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4401 FRNDINT               FRNDINT (no operands)
4402                       Round to integer                      Exceptions: I, P
4404 (no operands)         45         16-50          0           2       FRNDINT
4405 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4406 FRSTOR                FRSTOR source
4407                       Restore saved state                   Exceptions: None
4409 94-bytes                            (
4410 The 80287 execution clock count for this instruction is not meaningful
4411 in determining overall instruction execution time. For typical frequency
4412 ratios of the 80286 and 80287 clocks, 80287 execution occurs in parallel
4413 with the operand transfers, with the operand transfers determining the
4414 overall execution time of the instruction. For 80286:80287 clock frequency
4415 ratios of 4:8, 1:1, and 8:5, the overall execution clock count for this
4416 instruction is estimated at 490, 302, and 227 80287 clocks, respectively.)         47          2-4     FRSTOR [BP]
4417 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4418 FSAVE/FNSAVE          FSAVE/FNSAVE destination
4419                       Save state                            Exceptions: None
4421 94-bytes                            (
4422 The 80287 execution clock count for this instruction is not meaningful in
4423 determining overall instruction execution time. For typical frequency
4424 rations of the 80286 and 80287 clocks, 80287 execution occurs in parallel
4425 with the operand transfers, with the operand transfers determining the
4426 overall execution time of the instruction. For 80286:80287 clock frequency
4427 ratios of 4:8, 1:1, and 8:5, the overall execution clock count for this
4428 instruction is estimated at 376, 233, and 174 80287 clocks, respectively.)         47          2-4     FSAVE [BP]
4429 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4430 FSCALE                FSCALE (no operands)
4431                       Scale                                 Exceptions: I, O, U
4433 (no operands)         35         32-38           0           2      FSCALE
4434 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4435 FSETPM                FSETPM (no operands)
4436                       Set protected mode                    Exceptions: None
4438 (no operands)                     2-8            0           2      FSETPM
4439 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4440 FSQRT                 FSQRT (no operands)
4441                       Square root                           Exceptions: I, D, P
4443 (no operands)         183          80-186         0         2       FSQRT
4444 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4445 FST                   FST destination
4446                       Store real                            Exceptions: I, O, U, P
4448 ST(i)                  18          15-22          0         2       FST ST(3)
4449 short-real             87          84-90          2         2-4     FST CORRELATION [DI]
4450 long-real             100          96-104         4         2-4     FST MEAN_READING
4451 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4452 FSTCW/                FSTCW destination
4453 FNSTCW                Store control word                    Exceptions: None
4455 2-bytes               15           12-18          1         2-4     FSTCW SAVE_CONTROL
4456 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4457 FSTENV/               FSTENV destination
4458 FNSTENV               Store environment                     Exceptions: None
4460 14-bytes              45           40-50          7         2-4     FSTENV [BP]
4461 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4462 FSTP                  FSTP destination
4463                       Store real and pop                    Exceptions: I, O, U, P
4465 ST(i)                  20          17-24          0         2       FSTP ST(2)
4466 short-real             89          86-92          2         2-4     FSTP [BX].ADJUSTED_RPM
4467 long-real             102          98-106         4         2-4     FSTP TOTAL_DOSAGE
4468 temp-real              55          52-58          5         2-4     FSTP REG_SAVE [SI]
4469 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4470 FSTSW/                FSTSW destination
4471 FNSTSW                Store status word                     Exceptions: None
4473 2-bytes               15           12-18          1         2-4     FSTSW SAVE_STATUS
4474 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4475 FSTSW AX/             FSTSW AX
4476 FNSTSWAX              Store status word to AX               Exceptions: None
4478 AX                                 10-16          1         2       FSTSW AX
4479 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4480 FSUB                  FSUB //source/destination,source
4481                       Subtract real                         Exceptions: I, D, O, U, P
4483 //ST,ST(i)/ST(i),ST    85          70-100         0         2       FSUB ST,ST(2)
4484 short-real            105          90-120         2         2-4     FSUB BASE_VALUE
4485 long-real             110          95-125         4         2-4     FSUB COORDINATE.X
4486 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4487 FSUBP                 FSUBP destination, source
4488                       Subtract real and pop                 Exceptions: I, D, O, U, P
4490 ST(i),ST              90           75-105         0         2       FSUBP ST(2),ST
4491 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4492 FSUBR                 FSUBR //source/destination, source
4493                       Subtract real reversed                Exceptions: I, D, O, U, P
4495 //ST,ST(i)/ST(i),ST    87          70-100         0         2       FSUBR ST,ST(1)
4496 short-real            105          90-120         2         2-4     FSUBR VECTOR[SI]
4497 long-real             110          95-125         4         2-4     FSUBR [BX].INDEX
4498 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4499 FSUBRP                FSUBRP destination, source
4500                       Subtract real reversed and pop        Exceptions: I, D, O, U, P
4502 ST(i),ST              90           75-105         0         2       FSUBRP ST(1),ST
4503 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4504 FTST                  FTST (no operands)
4505                       Test stack top against +0.0           Exceptions: I, D
4506 (no operands)         42           38-48          0         2       FTST
4507 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4508 FWAIT                 FWAIT (no operands)
4509                       (CPU) Wait while 80287 is busy        Exceptions: None (CPU instruction)
4511 (no operands)         3+5n
4512 n = number of times CPU examines BUSY line before 80287 completes
4513 execution of previous instruction.        3+5n
4514 n = number of times CPU examines BUSY line before 80287 completes
4515 execution of previous instruction.          0         1       FWAIT
4516 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4517 FXAM                  FXAM (no operands)
4518                       Examine stack top                     Exceptions: None
4520 (no operands)         17           12-23          0         2       FXAM
4521 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4522 FXCH                  FXCH //destination
4523                       Exchange registers                            Exceptions: I
4525 //ST(i)               12           10-15          0         2       FXCH ST(2)
4526 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4527 FXTRACT               FXTRACT (no operands)
4528                       Extract exponent and significant              Exceptions: I
4530 (no operands)         50           27-55          0         2       FXTRACT
4531 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4532 FYL2X                 FYL2X (no operands)
4533                       Y * Log{2}X                           Exceptions: P (operands not checked)
4535 (no operands)         950        900-1100         0         2       FYL2X
4536 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4537 FYL2XP1               FYL2XP1 (no operands)
4538                       Y * log{2}(X + 1)                     Exceptions: P (operands not checked)
4540 (no operands)         850        700-1000         0         2       FYL2XP1
4541 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4542 F2XM1                 F2XM1 (no operands)
4543                       2^(2-1)                             Exceptions: U, P (operands not checked)
4545 (no operands)         500        310-630          0         2       F2XM1
4546 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
4550 Programming Facilities
4551 As described previously, the 80287 NPX is programmed simply as an extension
4552 of the 80286 CPU. This section describes how programmers in ASM286 and in a
4553 variety of higher-level languages can work with the 80287.
4555 The level of detail in this section is intended to give programmers a basic
4556 understanding of the software tools that can be used with the 80287, but
4557 this information does not document the full capabilities of these
4558 facilities. For a complete list of documentation on all the languages
4559 available for 80286 systems, readers should consult Intel's Literature
4560 Guide.
4563 High-Level Languages
4564 For programmers using high-level languages, the programming and operation
4565 of the NPX is handled automatically by the compiler. A variety of Intel
4566 high-level languages are available that automatically make use of the 80287
4567 NPX when appropriate. These languages include
4569   PL/M-286
4570   FORTRAN-286
4571   PASCAL-286
4572   C-286
4574 Each of these high-level languages has special numeric libraries allowing
4575 programs to take advantage of the capabilities of the 80287 NPX. No special
4576 programming conventions are necessary to make use of the 80287 NPX when
4577 programming numeric applications in any of these languages.
4579 Programmers in PL/M-286 and ASM286 can also make use of many of these
4580 library routines by using routines contained in the 80287 Support Library,
4581 described in the 80287 Support Library Reference Manual, Order Number
4582 122129. These library routines provide many of the functions provided by
4583 higher-level languages, including exception handlers,
4584 ASCII-to-floating-point conversions, and a more complete set of
4585 transcendental functions than that provided by the 80287 instruction set.
4588 PL/M-286
4589 Programmers in PL/M-286 can access a very useful subset of the 80287's
4590 numeric capabilities. The PL/M-286 REAL data type corresponds to the NPX's
4591 short real (32-bit) format. This data type provides a range of about
4592 8.43*10^(-37) ¾ ABS(X) ¾ 3.38*10^(38), with about seven significant
4593 decimal digits. This representation is adequate for the data manipulated by
4594 many microcomputer applications.
4596 The utility of the REAL data type is extended by the PL/M-286 compiler's
4597 practice of holding intermediate results in the 80287's temporary real
4598 format. This means that the full range and precision of the processor are
4599 utilized for intermediate results. Underflow, overflow, and rounding errors
4600 are most likely to occur during intermediate computations rather than during
4601 calculation of an expression's final result. Holding intermediate results in
4602 temporary real format greatly reduces the likelihood of overflow and
4603 underflow and eliminates roundoff as a serious source of error until the
4604 final assignment of the result is performed.
4606 The compiler generates 80287 code to evaluate expressions that contain REAL
4607 data types, whether variables or constants or both. This means that
4608 addition, subtraction, multiplication, division, comparison, and assignment
4609 of REALs will be performed by the NPX. INTEGER expressions, on the other
4610 hand, are evaluated on the CPU.
4612 Five built-in procedures (table 2-15) give the PL/M-286 programmer access
4613 to 80287 functions manipulated by the processor control instructions. Prior
4614 to any arithmetic operations, a typical PL/M-286 program will set up the NPX
4615 after power up using the INIT$REAL$MATH$UNIT procedure and then issue
4616 SET$REAL$MODE to configure the NPX. SET$REAL$MODE loads the 80287 control
4617 word, and its 16-bit parameter has the format shown in figure 1-5. The
4618 recommended value of this parameter is 033EH (projective closure, round to
4619 nearest, 64-bit precision, all exceptions masked except invalid operation).
4620 Other settings may be used at the programmer's discretion.
4622 If any exceptions are unmasked, an exception handler must be provided in
4623 the form of an interrupt procedure that is designated to be invoked by CPU
4624 interrupt pointer (vector) number 16. The exception handler can use the
4625 GET$REAL$ERROR procedure to obtain the low-order byte of the 80287 status
4626 word and to then clear the exception flags. The byte returned by
4627 GET$REAL$ERROR contains the exception flags; these can be examined to
4628 determine the source of the exception.
4630 The SAVE$REAL$STATUS and RESTORE$REAL$STATUS procedures are provided for
4631 multi-tasking environments where a running task that uses the 80287 may be
4632 preempted by another task that also uses the 80287. It is the responsibility
4633 of the preempting task to issue SAVE$REAL$STATUS before it executes any
4634 statements that affect the 80287; these include the INIT$REAL$MATH$UNIT and
4635 SET$REAL$MODE procedures as well as arithmetic expressions.
4636 SAVE$REAL$STATUS saves the 80287 state (registers, status, and control
4637 words, etc.) on the CPU's stack. RESTORE$REAL$STATUS reloads the state
4638 information; the preempting task must invoke this procedure before
4639 terminating in order to restore the 80287 to its state at the time the
4640 running task was preempted. This enables the preempted task to resume
4641 execution from the point of its preemption.
4644 Table 2-15. PL/M-286 Built-In Procedures
4646                          80287
4647 Procedure                Instruction        Description
4649 INIT$REAL$MATH$UNIT
4650 Also initializes interrupt pointers for emulation.     FINIT              Initialize processor.
4652 SET$REAL$MODE            FLDCW              Set exception masks, rounding
4653                                             precision, and infinity
4654                                             controls.
4656 GET$REAL$ERROR
4657 Returns low-order byte of status word.          FNSTSW & FNCLEX    Store, then clear, exception
4658                                             flags.
4660 SAVE$REAL$STATUS         FNSAVE             Save processor state.
4662 RESTORE$REAL$STATUS      FRSTOR             Restore processor state.
4665 ASM286
4666 The ASM286 assembly language provides programmmers with complete access to
4667 all of the facilities of the 80286 and 80287 processors.
4669 The programmer's view of the 80286/80287 hardware is a single machine with
4670 these resources:
4672   Ž  160 instructions
4673   Ž  12 data types
4674   Ž  8 general registers
4675   Ž  4 segment registers
4676   Ž  8 floating-point registers, organized as a stack
4679 Defining Data
4680 The ASM286 directives shown in table 2-16 allocate storage for 80287
4681 variables and constants. As with other storage allocation directives, the
4682 assembler associates a type with any variable defined with these directives.
4683 The type value is equal to the length of the storage unit in bytes (10 for
4684 DT, 8 for DQ, etc.). The assembler checks the type of any variable coded in
4685 an instruction to be certain that it is compatible with the instruction. For
4686 example, the coding FIADD ALPHA will be flagged as an error if ALPHA's type
4687 is not 2 or 4, because integer addition is only available for word and
4688 short integer data types. The operand's type also tells the assembler which
4689 machine instruction to produce; although to the programmer there is only an
4690 FIADD instruction, a different machine instruction is required for each
4691 operand type.
4693 On occasion it is desirable to use an instruction with an operand that has
4694 no declared type. For example, if register BX points to a short integer
4695 variable, a programmer may want to code FIADD [BX]. This can be done by
4696 informing the assembler of the operand's type in the instruction, coding
4697 FIADD DWORD PTR [BX]. The corresponding overrides for the other storage
4698 allocations are WORD PTR, QWORD PTR, and TBYTE PTR.
4700 The assembler does not, however, check the types of operands used in
4701 processor control instructions. Coding FRSTOR [BP] implies that the
4702 programmer has set up register BP to point to the stack location where the
4703 processor's 94-byte state record has been previously saved.
4705 The initial values for 80287 constants may be coded in several different
4706 ways. Binary integer constants may be specified as bit strings, decimal
4707 integers, octal integers, or hexadecimal strings. Packed decimal values are
4708 normally written as decimal integers, although the assembler will accept
4709 and convert other representations of integers. Real values may be written as
4710 ordinary decimal real numbers (decimal point required), as decimal numbers
4711 in scientific notation, or as hexadecimal strings. Using hexadecimal strings
4712 is primarily intended for defining special values such as infinities, NaNs,
4713 and nonnormalized numbers. Most programmers will find that ordinary decimal
4714 and scientific decimal provide the simplest way to initialize 80287
4715 constants. Figure 2-3 compares several ways of setting the various 80287
4716 data types to the same initial value.
4718 Note that preceding 80287 variables and constants with the ASM286 EVEN
4719 directive ensures that the operands will be word-aligned in memory. This
4720 will produce the best system performance. All 80287 data types occupy
4721 integral numbers of words so that no storage is "wasted" if blocks of
4722 variables are defined together and preceded by a single EVEN declarative.
4725 Table 2-16. 80287 Storage Allocation Directives
4727 Directive    Interpretation        Data Types
4729 DW           Define Word           Word integer
4730 DD           Define Doubleword     Short integer, short real
4731 DQ           Define Quadword       Long integer, long real
4732 DT           Define Tenbyte        Packed decimal, temporary real
4735 Records and Structures
4736 The ASM286 RECORD and STRUC (structure) declaratives can be very useful in
4737 NPX programming. The record facility can be used to define the bit fields of
4738 the control, status, and tag words. Figure 2-4 shows one definition of the
4739 status word and how it might be used in a routine that polls the 80287 until
4740 it has completed an instruction.
4742 Because STRUCtures allow different but related data types to be grouped
4743 together, they often provide a natural way to represent "real world" data
4744 organizations. The fact that the structure template may be "moved" about in
4745 memory adds to its flexibility. Figure 2-5 shows a simple structure that
4746 might be used to represent data consisting of a series of test score
4747 samples. A structure could also be used to define the organization of the
4748 information stored and loaded by the FSTENV and FLDENV instructions.
4751 Figure 2-3.  Sample 80287 Constants
4753   ;  THE FOLLOWING ALL ALLOCATE THE CONSTANT: -126
4754   ;  NOTE TWO'S COMPLETE STORAGE OF NEGATIVE BINARY INTEGERS.
4755   ;
4756      EVEN                                  ; FORCE WORK ALIGNMENT
4757   WORD_INTEGER    DW  111111111000010B     ; BIT STRING
4758   SHORT_INTEGER   DD  OFFFFFF82H           ; HEX STRING MUST START
4759                                            ; WITH DIGIT
4760   LONG_INTEGER    DQ  -126                 ; ORDINARY DECIMAL
4761   SHORT_REAL      DD  -126.0               ; NOTE PRESENCE OF '.'
4762   LONG_REAL       DD  -1.26E2              ; "SCIENTIFIC"
4763   PACKED_DECIMAL  DT  -126                 ; ORDINARY DECIMAL INTEGER
4765   ;  IN THE FOLLOWING, SIGN AND EXPONENT IS 'C005'
4766   ;     SIGNIFICAND IS '7E00...00', 'R' INFORMS ASSEMBLER THAT
4767   ;     THE STRING REPRESENTS A REAL DATA TYPE.
4768   ;
4769   TEMP_REAL       DT  0C0057E00000000000000R   ; HEX STRING
4772 Figure 2-4.  Status Word RECORD Definition
4774 ;  RESERVE SPACE FOR STATUS WORD
4775 STATUS_WORD
4776 ;  LAY OUT STATUS WORD FIELDS
4777 STATUS RECORD
4778 &    BUSY:               1,
4779 &    COND_CODE 3:        1,
4780 &    STACK_TOP:          3,
4781 &    COND_CODE 2:        1,
4782 &    COND_CODE 1:        1,
4783 &    COND_CODE 0:        1,
4784 &    INT_REQ:            1,
4785 &    RESERVED:           1,
4786 &    P_FLAG:             1,
4787 &    U_FLAG:             1,
4788 &    O_FLAG:             1,
4789 &    Z_FLAG:             1,
4790 &    D_FLAG:             1,
4791 &    I_FLAG:             1,
4792 ;  POLL STATUS WORD UNTIL 80287 IS NOT BUSY
4793 POLL:   FNSTSW   STATUS_WORD
4794         TEST     STATUS_WORD, MASK_BUSY
4795         JNZ      POLL
4798 Figure 2-5.  Structure Definition
4800   SAMPLE        STRUC
4802      N_OBS          DD    ?  ; SHORT INTEGER
4803      MEAN           DQ    ?  ; LONG REAL
4804      MODE           DW    ?  ; WORD INTEGER
4805      STD_DEV        DQ    ?  ; LONG REAL
4806      ; ARRAY OF OBSERVATIONS -- WORD INTEGER
4807      TEST_SCORES    DW    1000 DUP (?)
4808   SAMPLE ENDS
4811 Addressing Modes
4812 80287 memory data can be accessed with any of the CPU's five memory
4813 addressing modes. This means that 80287 data types can be incorporated in
4814 data aggregates ranging from simple to complex according to the needs of the
4815 application. The addressing modes, and the ASM286 notation used to specify
4816 them in instructions, make the accessing of structures, arrays, arrays of
4817 structures, and other organizations direct and straightforward. Table 2-17
4818 gives several examples of 80287 instructions coded with operands that
4819 illustrate different addressing modes.
4822 Table 2-17. Addressing Mode Examples
4824 ’‘‘‘ Coding‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“    Interpretation    
4826 FIADD   ALPHA                  ALPHA is a simple scalar (mode is direct).
4828 FDIVR   ALPHA.BETA             BETA is a field in a structure that is
4829                                "overlaid" on ALPHA (mode is direct).
4831 FMUL    QWORD PTR [BX]         BX contains the address of a long real
4832                                variable (mode is register indirect).
4834 FSUB    ALPHA [SI]             ALPHA is an array and SI contains the
4835                                offset of an array element from the start of
4836                                the array (mode is indexed).
4838 FILD    [BP].BETA              BP contains the address of a structure on
4839                                the CPU stack and BETA is a field in the
4840                                structure (mode is based).
4842 FBLD    TBYTE PTR [BX] [DI]    BX contains the address of a packed
4843                                decimal array and DI contains the offset of
4844                                an array element (mode is based indexed).
4847 Comparative Programming Example
4848 Figures 2-6 and 2-7 show the PL/M-286 and ASM286 code for a simple 80287
4849 program, called ARRSUM. The program references an array (X$ARRAY), which
4850 contains 0-100 short real values; the integer variable N$OF$X indicates the
4851 number of array elements the program is to consider. ARRSUM steps through
4852 X$ARRAY accumulating three sums:
4854   Ž  SUM$X, the sum of the array values
4856   Ž  SUM$INDEXES, the sum of each array value times its index, where the
4857      index of the first element is 1, the second is 2, etc.
4859   Ž  SUM$SQUARES, the sum of each array element squared
4861 (A true program, of course, would go beyond these steps to store and use
4862 the results of these calculations.) The control word is set with the
4863 recommended values: projective closure, round to nearest, 64-bit precision,
4864 interrupts enabled, and all exceptions masked invalid operation. It is
4865 assumed that an exception handler has been written to field the invalid
4866 operation, if it occurs, and that it is invoked by interrupt pointer 16.
4867 Either version of the program will run on an actual or an emulated 80287
4868 without altering the code shown.
4870 The PL/M-286 version of ARRSUM (figure 2-6) is very straightforward and
4871 illustrates how easily the 80287 can be used in this language. After
4872 declaring variables the program calls built-in procedures to initialize the
4873 processor (or its emulator) and to load to the control word. The program
4874 clears the sum variables and then steps through X$ARRAY with a DO-loop. The
4875 loop control takes into account PL/M-286's practice of considering the index
4876 of the first element of an array to be 0. In the computation of SUM$INDEXES,
4877 the built-in procedure FLOAT converts I+1 from integer to real because the
4878 language does not support "mixed mode" arithmetic. One of the strengths of
4879 the NPX, of course, is that it does support arithmetic on mixed data types
4880 (because all values are converted internally to the 80-bit temporary real
4881 format).
4883 The ASM286 version (figure 2-7) defines the external procedure INIT287,
4884 which makes the different initialization requirements of the processor and
4885 its emulator transparent to the source code. After defining the data and
4886 setting up the segment registers and stack pointer, the program calls
4887 INIT287 and loads the control word. The computation begins with the next
4888 three instructions, which clear three registers by loading (pushing) zeros
4889 onto the stack. As shown in figure 2-8, these registers remain at the
4890 bottom of the stack throughout the computation while temporary values are
4891 pushed on and popped off the stack above them.
4893 The program uses the CPU LOOP instruction to control its iteration through
4894 X_ARRAY; register CX, which LOOP automatically decrements, is loaded with
4895 N_OF_X, the number of array elements to be summed. Register SI is used to
4896 select (index) the array elements. The program steps through X_ARRAY from
4897 back to front, so SI is initialized to point at the element just beyond the
4898 first element to be processed. The ASM286 TYPE operator is used to determine
4899 the number of bytes in each array element. This permits  changing X_ARRAY to
4900 a long real array by simply changing its definition (DD to DQ) and
4901 reassembling.
4903 Figure 2-8 shows the effect of the instructions in the program loop on the
4904 NPX register stack. The figure assumes that the program is in its first
4905 iteration, that N_OF_X is 20, and that X_ARRAY(19) (the 20th element)
4906 contains the value 2.5. When the loop terminates, the three sums are left
4907 as the top stack elements so that the program ends by simply popping them
4908 into memory variables.
4911 Figure 2-6.  Sample PL/M-286 Program
4913 PL/M-286 COMPILER   ARRAYSUM
4915 SERIES-III PL/M-286 V 1.0 COMPILATION OF MODULE ARRAYSUM
4916 OBJECT MODULE PLACED IN :F6:D.OBJ
4917 COMPILER INVOLKED BY   PLM286.86 :F6:D.SRC XREF
4919             /******************************************
4920             *                                         *
4921             *     ARRAYSUM MOD                        *
4922             *                                         *
4923             ******************************************/
4925  1          array$sum:     do;
4927  2    1     declare (sum$x,sum$indexes,sum$squares) real;
4928  3    1     declare x$array(100) real;
4929  4    1     declare (n$of$x,i) integer;
4930  5    1     declare control$287 literally '033eh';
4932             /* Assume x$array and n$of$x are initalized */
4934             /* Prepare the 80287 of its emulator */
4935  6    1     call init$real$math$unit;
4936  7    1     call set$real$mode(control$287);
4938             /* Clear sums */
4939  8    1     sum$x, sum$indexes, (sum$squares - 0) 0;
4941             /* Loop through array, accumulating sums */
4942  9    1     do i = 0 to n$of$x-1;
4943 10    2       sum$x = sum$x = x$array(i);
4944 11    2       sum$indexes = sum$indexes +
4945                     (x$array(i) * float(i±1));
4946 12    2       sum$squares = sum$squares + (x$array(i)*x$array(i));
4947 13    2     end;
4949             /* etc. */
4951 14    1     end array$sum;
4953 PL/M-286 COMPILER     ARRAYSUM
4954                       CROSS-REFERENCE LISTING
4956 DEFN   ADDR   SIZE  NAME,ATTRIBUTES, AND REFERENCES
4958     1  0006H   117  ARRAYSUM             PROCEDURE STACK=002H
4959     5               CONTROL287           LITERALLY '033eh'    7
4960                     FLOAT                BUILTIN             11
4961     4  019EH     2  I                    INTEGER              9*    9    10    11    12    13
4962                     INITREALMATHUNIT     BUILTIN              6
4963     4  019CH     2  NDFX                 INTEGER              9
4964                     SETREALMODE          BUILTIN              7
4965     2  0004H     4  SUMINDEXES           REAL          8*    11    11*
4966     2  0008H     4  SUMSQAURES           REAL          8*    12    12*
4967     2  0000H     4  SUMX                 REAL          8*    10    10*
4968     3  000CH   400  XARRAY               REAL ARRAY(100)            10    11    12
4970 MODULE INFORMATION
4971       CODE AREA SIZE     = 0077H    119D
4972       CONSTANT AREA SIZE = 0004H      4D
4973       VARIABLE AREA SIZE = 01A0H    416D
4974       MAXIMUM STACK SIZE = 0002H      2D
4975       33 LINES READ
4976       0 PROGRAM WARNINGS
4977       0 PROGRAM ERRORS
4979 DICTIONARY SUMMARY
4980       96KB MEMORY AVILABLE
4981       3KB MEMORY USED  (3%)
4982       0KB DISK SPACE USED
4984 END OF PL/M-286 COMPILATION
4987 Figure 2-7.  Sample ASM286 Program
4989 iAPX286 MACRO ASSEMBLER     EXAMPLE ASM286_PROGRAM
4991 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE EXAMPLE_ASM286_PROGRAM
4992 OBJECT MODULE PLACED IN :F6:287EXP.OBJ
4993 ASSEMBLER INVOKED BY   ASM286 B6 :F6:287EXP.SRC XREF
4995 LOC  OBJ              LINE     SOURCE
4997                          1                 name    example_ASM286_program
4998                          2     ; Define intitialization routine
4999                          3                 extrn       init287:far
5000                          4
5001                          5     ;  Allocate space for date
5002 ----                     6     data        segment rw public
5003 0000 3E03                7     control_287     dw      033eh
5004 0002 ????                8     n_of_x          dw      ?
5005 0004 (000                9     x_array         dd      100 dwp (?)
5006      ????????
5007      )
5008 0194 ????????           10     sum_squares     dd      ?
5009 019B ????????           11     sum_indexes     dd      ?
5010 019C ????????           12     sum_x           dd      ?
5011 ----                    13     data     ends
5012                         14
5013                         15     ; Allocate CPU stack space
5014 ----                    16     stack       stackseg 400
5015                         17
5016                         18     ; Begin code
5017 ----                    19     code        segment or public
5018                         20                 assumes ds: data, ss: stack, es: nothing
5019 0000                    21     start:
5020 0000 BB----       R     22                 mov     ax,data
5021 0003 BED8               23                 mov     ds,ax
5022 0005 B8----       R     24                 mov     ax,stack
5023 0008 BED0               25                 mov     ss,ax
5024 000A BCFEFF       R     26                 mov     sp,stackstart stack
5025                         27
5026                         28     ; Assume x_array and n_of_x are initialized
5027                         29     ;           this pprogram zeroes n_of_x
5028                         30
5029                         31     ; Prepare the 80287 or its emulator
5030 000D 9A0000----   E     32                 call    init287
5031 0012 D92E0000     R     33                 fldcw   control_287
5032                         34
5033                         35     ; Clear three registers to hold running sums
5034 0016 D9EE               36                 fldz
5035 0018 D9EE               37                 fldz
5036 001A D9EE               38                 fldz
5037                         39
5038                         40     ; Setup CX as loop counter and
5039                         41     ; SI as index to x_array
5040 001C 8B0E0200     R     42                 mov     cx,n_of_x
5041 0020 F7E9               43                 imul    cx
5042 0022 8BF0               44                 mov     si,ax
5043                         45
5044                         46     ; SI now contains index of last element + 1
5045                         47     ; Loop thru x_array, accumulating sums
5046 0024                    48     sum_next:
5047 0024 8E3304             49                 sub     si,type x_array ;backup one element
5048 0027 D9840400     R     50                 fld     x_array[si]     ;push it on the stack
5049 002B DCC3               51                 fadd    st(3),st        ;add into sum of x
5050 002D D9C0               52                 fld     st              ;duplicate x on tap
5051 002F DCC8               53                 fmul    st,st           ;square it
5052 0031 DEC2               54                 faddp   st(2),st        ;add into sum of (index+x)
5053                         55                                         ;  and discard
5054 0033 FF0E0200     R     56                 dec     n_of_x          ;reduce index for next iteration
5055 0037 E2EB               57                 loop    sum_next                ;continue
5056                         58
5057                         59     ; Pop running sums into memory
5058 0039                    60     pop_results:
5059 0039 D91E9401     R     61                 fstp    sum_squares
5060 003D D91E9801     R     62                 fstp    sum_indexes
5061 0041 D91E9C01     R     63                 fstp    sum_x
5062 0045 9B                 64                 fwait
5063                         65
5064                         66     ;
5065                         67     ; Etc.
5066                         68     ;
5067 ----                    69     code        ends
5068                         70                 end     start
5070 iAPX286 MACRO ASSEMBLER     EXAMPLE_ASM286_PROGRAM
5071 XREF SYMBOL TABLE LISTING
5073 NAME          TYPE      VALUE   ATTRIBUTES, XREFS
5075 CODE          SEGMENT           SIZE=0046H ER PUBLIC  19# 69
5076 CONTROL_287   V WORD    0000H   DATA  7# 33
5077 DATA          SEGMENT           SIZE=01A0H RW PUBLIC   6# 13 20 22
5078 INIT287       L FAR     0000H   EXTR   3# 32
5079 N_OF_X        V WORD    0002H   DATA   8# 42 56
5080 POP_RESULTS   L NEAR    0039H   CODE   60#
5081 STACK         STACK             SIZE=0190H RW PUBLIC   16# 20 24 26
5082 START         L NEAR    0000H   CODE   21# 70
5083 SUM_INDEXES   V DWORD   0198H   DATA   11# 62
5084 SUM_NEXT      L NEAR    0024H   CODE   48# 57
5085 SUM_SQUARES   V DWORD   0194H   DATA   10# 61
5086 SUM_X         V DWORD   019CH   DATA   12# 63
5087 X_ARAY        V DWORD   0004H   (100) DATA   9# 49 50
5089 END OF SYMBOL TABLE LISTING
5091 ASSEMBLY COMPLETE,                  NO ERRORS
5094 Figure 2-8.  Instructions and Register Stack
5096           FLDZ,FLDZ,FLDZ                    FDL X_ARRAY[SI]
5097              ‚�����ƒ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘\x10‚�����ƒ
5098         ST(0)€ 0.0 € SUM_SQUARES          ST(0)€ 2.5 € X_ARRAY(19)
5099              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5100         ST(1)€ 0.0 € SUM_INDEXES          ST(1)€     € SUM_SQUARES
5101              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5102         ST(2)€ 0.0 € SUM_X                ST(2)€ 0.0 € SUM_INDEXES
5103              „�����…                           Ã‘‘‘‘‘Â
5104                                           ST(3)€ 0.0 € SUM_X
5105                       ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘„�����…
5106                       �
5107          FADD ST(3),ST�                         FLD ST
5108              ‚�����ƒ\x11‘•‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘\x10‚�����ƒ
5109         ST(0)€ 2.5 € X_ARRAY(19)          ST(0)€ 2.5 € X_ARRAY(19)
5110              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5111         ST(1)€ 0.0 € SUM_SQUARES          ST(1)€ 2.5 € X_ARRAY(19)
5112              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5113         ST(2)€ 0.0 € SUM_INDEXES          ST(2)€ 0.0 € SUM_SQUARES
5114              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5115         ST(3)€ 2.5 € SUM_X                ST(3)€ 0.0 € SUM_INDEXES
5116              „�����…                           Ã‘‘‘‘‘Â
5117                                           ST(4)€ 2.5 € SUM_X
5118                       ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘„�����…
5119                       �
5120             FMUL ST,ST�                     FADDP ST(2),ST
5121              ‚�����ƒ\x11‘•‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘\x10‚�����ƒ
5122         ST(0)€ 6.25€ X_ARRAY(19)^(2)      ST(0)€ 2.5 € X_ARRAY(19)
5123              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5124         ST(1)€ 2.5 € X_ARRAY(19)          ST(1)€ 6.25€ SUM_SQUARES
5125              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5126         ST(2)€ 0.0 € SUM_SQUARES          ST(2)€ 0.0 € SUM_INDEXES
5127              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5128         ST(3)€ 0.0 € SUM_INDEXES          ST(3)€ 2.5 € SUM_X
5129              Ã‘‘‘‘‘               ’‘‘‘‘‘‘‘‘‘‘‘„�����…
5130         ST(4)€ 2.5 € SUM_X         �
5131              „�����…               �
5132                        ’‘‘‘‘‘‘‘‘‘‘‘•
5133            FIMUL N_OF_X�                     FADDP ST(2),ST
5134              ‚�����ƒ\x11‘‘•‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘\x10‚�����ƒ
5135         ST(0)€ 50.0€ X_ARRAY(19)*20       ST(0)€ 6.25€ SUM_SQUARES
5136              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5137         ST(1)€ 6.25€ SUM_SQUARES          ST(1)€ 50.0€ SUM_INDEXES
5138              Ã‘‘‘‘‘                           Ã‘‘‘‘‘Â
5139         ST(2)€ 0.0 € SUM_INDEXES          ST(2)€ 2.5 € SUM_X
5140              Ã‘‘‘‘‘                           „�����…
5141         ST(3)€ 2.5 € SUM_X
5142              „�����…
5145 80287 Emulation
5146 The programming of applications to execute on both 80286 and 80287 is made
5147 much easier by the existence of an 80287 emulator for 80286 systems. The
5148 Intel E80287 emulator offers a complete software counterpart to the 80287
5149 hardware; NPX instructions can be simply emulated in software rather than
5150 being executed in hardware. With software emulation, the distinction
5151 between 80286 and 80287 systems is reduced to a simple performance
5152 differential (see Table 1-2 for a performance comparison between an actual
5153 80287 and an emulator 80287).  Identical numeric programs will simply
5154 execute more slowly on 80286 systems (using software emulation of NPX
5155 instructions) than on executing NPX instructions directly.
5157 When incorporated into the systems software, the emulation of NPX
5158 instructions on the 80286 systems is completely transparent to the
5159 programmer. Applications software needs no special libraries, linking, or
5160 other activity to allow it to run on an 80286 with 80287 emulation.
5162 To the applications programmer, the development of programs for 80286
5163 systems is the same whether the 80287 NPX hardware is available or not. The
5164 full 80287 instruction set is available for use, with NPX instructions being
5165 either emulated or executed directly. Applications programmers need not be
5166 concerned with the hardware configuration of the computer systems on which
5167 their applications will eventually run.
5169 For systems programmers, details relating to 80287 emulators are described
5170 in a later section of this supplement. An E80287 software emulator for 80286
5171 systems is contained in the iMDX 364 8086 Software Toolbox, available from
5172 Intel and described in the 8086 Software Toolbox Manual.
5175 Concurrent Processing with the 80287
5176 Because the 80286 CPU and the 80287 NPX have separate execution units, it
5177 is possible for the NPX to execute numeric instructions in parallel with
5178 instructions executed by the CPU. This simultaneous execution of different
5179 instructions is called concurrency.
5181 No special programming techniques are required to gain the advantages of
5182 concurrent execution; numeric instructions for the NPX are simply placed in
5183 line with the instructions for the CPU. CPU and numeric instructions are
5184 initiated in the same order as they are encountered by the CPU in its
5185 instruction stream. However, because numeric operations performed by the NPX
5186 generally require more time than operations performed by the CPU, the CPU
5187 can often execute several of its instructions before the NPX completes a
5188 numeric instruction previously initiated.
5190 This concurrency offers obvious advantages in terms of execution
5191 performance, but concurrency also imposes several rules that must be
5192 observed in order to assure proper synchronization of the 80286 CPU and
5193 80287 NPX.
5195 All Intel high-level languages automatically provide for and manage
5196 concurrency in the NPX. Assembly-language programmers, however, must
5197 understand and manage some areas of concurrency in exchange for the
5198 flexibility and performance of programming in assembly language. This
5199 section is for the assembly-language programmer or well-informed
5200 high-level-language programmer.
5203 Managing Concurrency
5204 Concurrent execution of the host and 80287 is easy to establish and
5205 maintain. The activities of numeric programs can be split into two major
5206 areas: program control and arithmetic. The program control part performs
5207 activities such as deciding what functions to perform, calculating
5208 addresses of numeric operands, and loop control. The arithmetic part simply
5209 adds, subtracts, multiplies, and performs other operations on the numeric
5210 operands. The NPX and host are designed to handle these two parts
5211 separately and efficiently.
5213 Managing concurrency is necessary because both the arithmetic and control
5214 areas must converge to a well-defined state before starting another numeric
5215 operation. A well-defined state means all previous arithmetic and control
5216 operations are complete and valid.
5218 Normally, the host waits for the 80287 to finish the current numeric
5219 operation before starting another. This waiting is called synchronization.
5221 Managing concurrent execution of the 80287 involves three types of
5222 synchronization:
5224   1.  Instruction synchronization
5225   2.  Data synchronization
5226   3.  Error synchronization
5228 For programmers in higher-level languages, all three types of
5229 synchronization are automatically provided by the appropriate compiler. For
5230 assembly-language programmers, instruction synchronization is guaranteed by
5231 the NPX interface, but data and error synchronization are the
5232 responsibility of the assembly-language programmer.
5235 Instruction Synchronization
5236 Instruction synchronization is required because the 80287 can perform only
5237 one numeric operation at a time. Before any numeric operation is started,
5238 the 80287 must have completed all activity from its previous instruction.
5240 Instruction synchronization is guaranteed for most ESC instructions because
5241 the 80286 automatically checks the BUSY status line from the 80287
5242 before commencing execution of most ESC instructions. No explicit WAIT
5243 instructions are necessary to ensure proper instruction synchronization.
5246 Data Synchronization
5247 Data synchronization addresses the issue of both the CPU and the NPX
5248 referencing the same memory values within a given block of code.
5249 Synchronization ensures that these two processors access the memory operands
5250 in the proper sequence, just as they would be accessed by a single
5251 processor with no concurrency. Data synchronization is not a concern when
5252 the CPU and NPX are using different memory operands during the course of one
5253 numeric instruction.
5255 The two cases where data synchronization might be a concern are
5257   1.  The 80286 CPU reads or alters a memory operand first, then invokes
5258       the 80287 to load or alter the same operand.
5260   2.  The 80287 is invoked to load or alter a memory operand, after which
5261       the 80286 CPU reads or alters the same location.
5263 Due to the instruction synchronization of the NPX interface, data
5264 synchronization is automatically provided for the first case‘‘the 80286 will
5265 always complete its operation before invoking the 80287.
5267 For the second case, data synchronization is not always automatic. In
5268 general, there is no guarantee that the 80287 will have finished its
5269 processing and accessed the memory operand before the 80286 accesses the
5270 same location.
5272 Figure 2-9 shows examples of the two possible cases of the CPU and NPX
5273 sharing a memory value. In the examples of the first case, the CPU will
5274 finish with the operand before the 80287 can reference it. The NPX interface
5275 guarantees this. In the examples of the second case, the CPU must wait for
5276 the 80287 to finish with the memory operand before proceeding to reuse it.
5277 The FWAIT instructions shown in these examples are required in order to
5278 ensure this data synchronization.
5280 There are several NPX control instructions where automatic data
5281 synchronization is provided; however, the FSTSW/FNSTSW, FSTCW/FNSTCW, FLDCW,
5282 FRSTOR, and FLDENV instructions are all guaranteed to finish their execution
5283 before the CPU can read or alter the referenced memory locations.
5285 The 80287 provides data synchronization for these instructions by making a
5286 request on the Processor Extension Data Channel before the CPU executes its
5287 next instruction. Since the NPX data transfers occur before the CPU regains
5288 control of the local bus, the CPU cannot change a memory value before the
5289 NPX has had a chance to reference it. In the case of the FSTSW AX
5290 instruction, the 80286 AX register is explicitly updated before the CPU
5291 continues execution of the next instruction.
5293 For the numeric instructions not listed above, the assembly-language
5294 programmer must remain aware of synchronization and recognize cases
5295 requiring explicit data synchronization. Data synchronization can be
5296 provided either by programming an explicit FWAIT instruction, or by
5297 initiating a subsequent numeric instruction before accessing the operands or
5298 results of a previous instruction. After the subsequent numeric instruction
5299 has started execution, all memory references in earlier numeric
5300 instructions are complete. Reaching the next host instruction after the
5301 synchronizing numeric instruction indicates that previous numeric operands
5302 in memory are available.
5304 The data-synchronization function of any FWAIT or numeric instruction must
5305 be well-documented, as shown in figure 2-10. Otherwise, a change to the
5306 program at a later time may remove the synchronizing numeric instruction and
5307 cause program failure.
5309 High-level languages automatically establish data synchronization and
5310 manage it, but there may be applications where a high-level language may not
5311 be appropriate.
5313 For assembly-language programmers, automatic data synchronization can be
5314 obtained using the assembler, although concurrency of execution is lost as a
5315 result. To perform automatic data synchronization, the assembler can be
5316 changed to always place a WAIT instruction after the ESCAPE instruction.
5317 Figure 2-11 shows an example of how to change the ASM286 Code Macro for the
5318 FIST instruction to automatically place a WAIT instruction after the ESCAPE
5319 instruction. This Code Macro is included in the ASM286 source module. The
5320 price paid for this automatic data synchronization is the lack of any
5321 possible concurrency between the CPU and NPX.
5324 Figure 2-9.  Synchronizing References to Shared Data
5326   Case 1:                Case 2:
5327        MOV     I,  1          FILD      I
5328        FILD    I              FWAIT
5329                               MOV       I, 5
5331        MOV     AX, I          FISTP     I
5332        FISTP   I              FWAIT
5333                               MOV       AX, I
5336 Figure 2-10.  Documenting Data Synchronization
5338   FISTP   I
5339   FMUL                ; I is updated before FMUL is executed
5340   MOV     AX, I       ; I is now safe to use
5343 Figure 2-11.  Nonconcurrent FIST Instruction Code Macro
5345   ;
5346   ; This is an ASM286 code macro to redefine the FIST
5347   ; instruction to prevent any concurrency
5348   ; while the instruction runs. A wait
5349   ; instruction is placed immediately after the
5350   ; escape to ensure the store is done
5351   ; before the program may continue.
5352   CodeMacro FIST memop: Mw
5353   RfixM 111B, memop
5354   ModRM 010B, memop
5355   RWfix
5356   EndM
5359 Error Synchronization
5360 Almost any numeric instruction can, under the wrong circumstances, produce
5361 a numeric error. Concurrent execution of the CPU and NPX requires
5362 synchronization for these errors just as it does for data references and
5363 numeric instructions. In fact, the synchronization required for data and
5364 instructions automatically provides error synchronization.
5366 However, incorrect data or instruction synchronization may not be
5367 discovered until a numeric error occurs. A further complication is that a
5368 programmer may not expect his numeric program to cause numeric errors, but
5369 in some systems, they may regularly happen. To better understand these
5370 points, let's look at what can happen when the NPX detects an error.
5372 The NPX can perform one of two things when a numeric exception occurs:
5374   Ž  The NPX can provide a default fix-up for selected numeric errors.
5375      Programs can mask individual error types to indicate that the NPX
5376      should generate a safe, reasonable result whenever that error occurs.
5377      The default error fix-up activity is treated by the NPX as part of the
5378      instruction causing the error; no external indication of the error is
5379      given. When errors are detected, a flag is set in the numeric status
5380      register, but no information regarding where or when is available. If
5381      the NPX performs its default action for all errors, then error
5382      synchronization is never exercised. This is no reason to ignore error
5383      synchronization, however.
5385   Ž  As an alternative to the NPX default fix-up of numeric errors, the
5386      80286 CPU can be notified whenever an exception occurs. The CPU can
5387      then implement any sort of recovery procedures desired, for any numeric
5388      error detectable by the NPX. When a numeric error is unmasked and the
5389      error occurs, the NPX stops further execution of the numeric
5390      instruction and signals this event to the CPU. On the next occurrence
5391      of an ESC or WAIT instruction, the CPU traps to a software exception
5392      handler. Some ESC instructions do not check for errors. These are the
5393      nonwaited forms FNINIT, FNSTENV, FNSAVE, FNSTSW, FNSTCW, and FNCLEX.
5395 When the NPX signals an unmasked exception condition, it is requesting
5396 help. The fact that the error was unmasked indicates that further numeric
5397 program execution under the arithmetic and programming rules of the NPX is
5398 unreasonable.
5400 If concurrent execution is allowed, the state of the CPU when it recognizes
5401 the exception is undefined. The CPU may have changed many of its internal
5402 registers and be executing a totally different program by the time the
5403 exception occurs. To handle this situation, the NPX has special registers
5404 updated at the start of each numeric instruction to describe the state of
5405 the numeric program when the failed instruction was attempted.
5407 Error synchronization ensures that the NPX is in a well-defined state after
5408 an unmasked numeric error occurs. Without a well-defined state, it would be
5409 impossible for exception recovery routines to figure out why the numeric
5410 error occurred, or to recover successfully from the error.
5413 Incorrect Error Synchronization
5414 An example of how some instructions written without error synchronization
5415 will work initially, but fail when moved into a new environment is shown in
5416 figure 2-12.
5418 In figure 2-12, three instructions are shown to load an integer, calculate
5419 its square root, then increment the integer. The NPX interface and
5420 synchronous execution of the NPX emulator will allow this program to execute
5421 correctly when no errors occur on the FILD instruction.
5423 This situation changes if the 80287 numeric register stack is extended to
5424 memory. To extend the NPX stack to memory, the invalid error is unmasked. A
5425 push to a full register or pop from an empty register will cause an invalid
5426 error. The recovery routine for the error must recognize this situation,
5427 fix up the stack, then perform the original operation.
5429 The recovery routine will not work correctly in the first example shown in
5430 the figure. The problem is that the value of COUNT is incremented before the
5431 NPX can signal the exception to the CPU. Because COUNT is incremented before
5432 the exception handler is invoked, the recovery routine will load an
5433 incorrect value of COUNT, causing the program to fail or behave unreliably.
5436 Figure 2-12. Error Synchronization Examples
5438                   INCORRECT ERROR SYNCHRONIZATION
5440 FILD   COUNT   ; NPX instruction
5441 INC    COUNT   ; CPU instruction alters operand
5442 FSQRT  COUNT   ; subsequent NPX instruction -- error from
5443                ;    previous NPX instruction detected here
5445                     PROPER ERROR SYNCHRONIZATION
5447 FILD   COUNT   ; NPX instruction
5448 FSQRT  COUNT   ; subsequent NPX instruction - error from
5449                ;    previous NPX instruction detected here
5450 INC    COUNT   ; CPU instruction alters operand
5453 Proper Error Synchronization
5454 Error Synchronization relies on the WAIT instructions required by
5455 instruction and data synchronization and the BUSY and ERROR signals of
5456 the 80287. When an unmasked error occurs in the 80287, it asserts the
5457 ERROR signal, signalling to the CPU that a numeric error has occurred.
5458 The next time the CPU encounters an error-checking ESC or WAIT instruction,
5459 the CPU acknowledges the ERROR signal by trapping automatically to
5460 Interrupt #16, the Processor Extension Error vector. If the following ESC
5461 or WAIT instruction is properly placed, the CPU will not yet have disturbed
5462 any information vital to recovery from the error.
5465 Chapter 3  System-Level Numeric Programming
5467 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
5469 System programming for 80287 systems requires a more detailed understanding
5470 of the 80287 NPX than does application programming. Such things as
5471 emulation, initialization, exception handling, and data and error
5472 synchronization are all the responsibility of the systems programmer. These
5473 topics are covered in detail in the sections that follow.
5476 80287 Architecture
5477 On a software level, the 80287 NPX appears as an extension of the 80286
5478 CPU. On the hardware level, however, the mechanisms by which the 80286 and
5479 80287 interact are a bit more complex. This section describes how the 80287
5480 NPX and 80286 CPU interact and points out features of this interaction that
5481 are of interest to systems programmers.
5484 Processor Extension Data Channel
5485 All transfers of operands between the 80287 and system memory are performed
5486 by the 80286's internal Processor Extension Data Channel. This independent,
5487 DMA-like data channel permits all operand transfers of the 80287 to come
5488 under the supervision of the 80286 memory-management and protection
5489 mechanisms. The operation of this data channel is completely transparent to
5490 software.
5492 Because the 80286 actually performs all transfers between the 80287 and
5493 memory, no additional bus drivers, controllers, or other components are
5494 necessary to interface the 80287 NPX to the local bus. Any memory accessible
5495 to the 80286 CPU is accessible by the 80287. The Processor Extension Data
5496 Channel is described in more detail in Chapter Six of the 80286 Hardware
5497 Reference Manual.
5500 Real-Address Mode and Protected Virtual-Address Mode
5501 Like the 80286 CPU, the 80287 NPX can operate in both Real-Address mode and
5502 in Protected mode. Following a hardware RESET, the 80287 is initially
5503 activated in Real-Address mode. A single, privileged instruction (FSETPM) is
5504 necessary to set the 80287 into Protected mode.
5506 As an extension to the 80286 CPU, the 80287 can access any memory location
5507 accessible by the task currently executing on the 80286. When operating in
5508 Protected mode, all memory references by the 80287 are automatically
5509 verified by the 80286's memory management and protection mechanisms as for
5510 any other memory references by the currently-executing task. Protection
5511 violations associated with NPX instructions automatically cause the 80286 to
5512 trap to an appropriate exception handler.
5514 To the programmer, these two 80287 operating modes differ only in the
5515 manner in which the NPX instruction and data pointers are represented in
5516 memory following an FSAVE or FSTENV instruction. When the 80287 operates in
5517 Protected mode, its NPX instruction and data pointers are each represented
5518 in memory as a 16-bit segment selector and a 16-bit offset. When the 80287
5519 operates in Real-Address mode, these same instruction and data pointers are
5520 represented simply as the 20-bit physical addresses of the operands in
5521 question (see figure 1-7 in Chapter One).
5524 Dedicated and Reserved I/O Locations
5525 The 80287 NPX does not require that any memory addresses be set aside for
5526 special purposes. The 80287 does make use of I/O port addresses in the range
5527 00F8H through 00FFH, although these I/O operations are completely
5528 transparent to the 80286 software. 80286 programs must not reference these
5529 reserved I/O addresses directly.
5531 To prevent any accidental misuse or other tampering with numeric
5532 instructions in the 80287, the 80286's I/O Privilege Level (IOPL) should be
5533 used in multiuser reprogrammable environments to restrict application
5534 program access to the I/O address space and so guarantee the integrity of
5535 80287 computations. Chapter Eight of the 80286 Operating System Writer's
5536 Guide contains more details regarding the use of the I/O Privilege Level.
5539 Processor Initialization and Control
5540 One of the principal responsibilities of systems software is the
5541 initialization, monitoring, and control of the hardware and software
5542 resources of the system, including the 80287 NPX. In this section, issues
5543 related to system initialization and control are described, including
5544 recognition of the NPX, emulation of the 80287 NPX in software if the
5545 hardware is not available, and the handling of exceptions that may occur
5546 during the execution of the 80287.
5549 System Initialization
5550 During initialization of an 80286 system, systems software must
5552   Ž  Recognize the presence or absence of the NPX
5554   Ž  Set flags in the 80286 MSW to reflect the state of the numeric
5555      environment
5557 If an 80287 NPX is present in the system, the NPX must be
5559   Ž  Initialized
5561   Ž  Switched into Protected mode (if desired)
5563 All of these activities can be quickly and easily performed as part of the
5564 overall system initialization.
5567 Recognizing the 80287 NPX
5568 Figure 3-1 shows an example of a recognition routine that determines
5569 whether an NPX is present, and distinguishes between the 80387 and the
5570 8087/80287. This routine can be executed on any 80386, 80286, or 8086
5571 hardware configuration that has an NPX socket.
5573 The example guards against the possibility of accidentally reading an
5574 expected value from a floating data bus when no NPX is present. Data read
5575 from a floating bus is undefined. By expecting to read a specific bit
5576 pattern from the NPX, the routine protects itself from the indeterminate
5577 state of the bus. The example also avoids depending on any values in
5578 reserved bits, thereby maintaining compatibility with future numerics
5579 coprocessors.
5582 Figure 3-1.  Software Routine to Recognize the 80287
5584 ;  The following algorithm detects the presence of the 8087 as well as the
5585 ;  80287 in a system.  This will make it easier for ISVs to port their 8086-87
5586 ;  software to 286-287 systems.
5588             cc_cr               equ     0DH     ;  carriage return
5589             cc_lf               equ     0AH     ;  line feed
5591 assume      cz:code, ds:data
5593 code        segment             public
5594 start:
5595             mov     ax,data                 ;  set data segment
5596             mov     ds,ax
5598 ;  Test if 8087 is present in PC or PC/XT, or 80287 is in PC/AT
5600             fninit                          ;  initialize coprocessor
5601             xor     ah,ah                   ;  zero ah register and memory byte
5602             mov     byte ptr control + 1,ah
5603             fnstcw  control                 ;  store coprocessor's control word in
5604                                             ;  memory
5605             mov     ah,byte ptr control+1
5606             cmp     ah,03h                  ;  upper byte of control work will be
5607                                             ;  03 if 8087 or 80287 coprocessor
5608                                             ;  is present
5609             jne     no_coproc
5611 coproc:
5612             mov     ah,09h                  ;  print string-coprocessor present
5613             mov     dx,offset msg_yes
5614             int     21h
5615             jmp     done
5618 no_coproc:
5619             mov     ah,09h                  ; print string-coprocessor not
5620                                             ; present
5621             mov     dx,offset msg_no
5622             int     21h
5624 done:
5625             mov     ah,4CH                  ; terminate program
5626             int     21h
5627 code        ends
5629 data        segment         public
5630 control     dw              00
5631 msg_yes     db      cc_cr,cc_lf,
5632             db      'System has an 8087 or 80287',cc_cr, cc_lf, '$'
5633 msg_no      db      cc_cr,cc_lf,
5634             db      'System does not have an 8087 or 80287',cc_cr, cc_lf,
5635                      '$'
5636 data        ends
5637             end     start                   ; start is the entry point
5640 Configuring the Numerics Environment
5641 Once the 80286 CPU has determined the presence or absence of the 80287 NPX,
5642 the 80286 must set either the MP or the EM bit in its own machine status
5643 word accordingly. The initialization routine can either
5645   Ž  Set the MP bit in the 80286 MSW to allow numeric instructions to be
5646      executed directly by the 80287 NPX component
5648   Ž  Set the EM bit in the 80286 MSW to permit software emulation of the
5649      80287 numeric instructions
5651 The Math Present (MP) flag of the 80286 machine status word indicates to
5652 the CPU whether an 80287 NPX is physically available in the system. The MP
5653 flag controls the function of the WAIT instruction. When executing a WAIT
5654 instruction, the 80286 tests only the Task Switched (TS) bit if MP is set;
5655 if it finds TS set under these conditions, the CPU traps to exception #7.
5657 The Emulation Mode (EM) bit of the 80286 machine status word indicates to
5658 the CPU whether NPX functions are to be emulated. If the CPU finds EM set
5659 when it executes an ESC instruction, program control is automatically
5660 trapped to exception #7, giving the exception handler the opportunity to
5661 emulate the functions of an 80287. The 80286 EM flag can be changed only by
5662 using the LMSW (load machine status word) instruction (legal only at
5663 privilege level 0) and examined with the aid of the SMSW (store machine
5664 status word) instruction (legal at any privilege level).
5666 The EM bit also controls the function of the WAIT instruction. If the CPU
5667 finds EM set while executing a WAIT, the CPU does not check the ERROR
5668 pin for an error indication.
5670 For correct 80286 operation, the EM bit must never be set concurrently with
5671 MP. The EM and MP bits of the 80286 are described in more detail in the
5672 80286 Operating System Writer's Guide. More information on software
5673 emulation for the 80287 NPX is described in the "80287 Emulation" section
5674 later in this chapter.
5676 In any case, if ESC instructions are to be executed, either the MP or EM
5677 bit must be set, but not both.
5680 Initializing the 80287
5681 Initializing the 80287 NPX simply means placing the NPX in a known state
5682 unaffected by any activity performed earlier. The example software routine
5683 to recognize the 80287 (figure 3-1) performed this initialization using a
5684 single FNINIT instruction. This instruction causes the NPX to be
5685 initialized in the same way as that caused by the hardware RESET signal to
5686 the 80287. All the error masks are set, all registers are tagged empty, the
5687 ST is set to zero, and default rounding, precision, and infinity controls
5688 are set. Table 3-1 shows the state of the 80287 NPX following
5689 initialization.
5691 Following a hardware RESET signal, such as after initial power-up, the
5692 80287 is initialized in Real-Address mode. Once the 80287 has been switched
5693 to Protected mode (using the FSETPM instruction), only another hardware
5694 RESET can switch the 80287 back to Real-Address mode. The FNINIT instruction
5695 does not switch the operating state of the 80287.
5698 80287 Emulation
5699 If it is determined that no 80287 NPX is available in the system, systems
5700 software may decide to emulate ESC instructions in software. This emulation
5701 is easily supported by the 80286 hardware, because the 80286 can be
5702 configured to trap to a software emulation routine whenever it encounters
5703 an ESC instruction in its instruction stream.
5705 As described previously, whenever the 80286 CPU encounters an ESC
5706 instruction, and its MP and EM status bits are set appropriately (MP = 0,
5707 EM = 1), the 80286 will automatically trap to interrupt #7, the Processor
5708 Extension Not Available exception. The return link stored on the stack
5709 points to the first byte of the ESC instruction, including the prefix
5710 byte(s), if any. The exception handler can use this return link to examine
5711 the ESC instruction and proceed to emulate the numeric instruction in
5712 software.
5714 The emulator must step the return pointer so that, upon return from the
5715 exception handler, execution can resume at the first instruction following
5716 the ESC instruction.
5718 To an application program, execution on an 80286 system with 80287
5719 emulation is almost indistinguishable from execution on an 80287  system,
5720 except for the difference in execution speeds.
5722 There are several important considerations when using emulation on an 80286
5723 system:
5725   Ž  When operating in Protected-Address mode, numeric applications using
5726      the emulator must be executed in execute-readable code segments.
5727      Numeric software cannot be emulated if it is executed in execute-only
5728      code segments. This is because the emulator must be able to examine
5729      the particular numeric instruction that caused the Emulation trap.
5731   Ž  Only privileged tasks can place the 80286 in emulation mode. The
5732      instructions necessary to place the 80286 in Emulation mode are
5733      privileged instructions, and are not typically accessible to an
5734      application.
5736 An emulator package (E80287) that runs on 80286 systems is available from
5737 Intel in the 8086 Software Toolbox, Order Number 122203. This emulation
5738 package operates in both Real and Protected mode, providing a complete
5739 functional equivalent for the 80287 emulated in software.
5741 When using the E80287 emulator, writers of numeric exception handlers
5742 should be aware of one slight difference between the emulated 80287 and the
5743 80287 hardware:
5745   Ž  On the 80287 hardware, exception handlers are invoked by the 80286 at
5746      the first WAIT or ESC instruction following the instruction causing the
5747      exception. The return link, stored on the 80286 stack, points to this
5748      second WAIT or ESC instruction where execution will resume following a
5749      return from the exception handler.
5751   Ž  Using the E80287 emulator, numeric exception handlers are invoked from
5752      within the emulator itself. The return link stored on the stack when
5753      the exception handler is invoked will therefore point back to the
5754      E80287 emulator, rather than to the program code actually being
5755      executed (emulated). An IRET return from the exception handler returns
5756      to the emulator, which then returns immediately to the emulated
5757      program. This added layer of indirection should not cause confusion,
5758      however, because the instruction causing the exception can always be
5759      identified from the 80287's instruction and data pointers.
5762 Table 3-1. NPX Processor State Following Initialization
5765 Field                    Value         Interpretation
5767 Control Word
5768  Infinity Control         0            Projective
5769  Rounding Control         00           Round to nearest
5770  Precision Control        11           64 bits
5771  Interrupt-Enable Mask    1            Interrupts disabled
5772  Exception Masks          111111       All exceptions masked
5774 Status Word
5775  Busy                     0            Not busy
5776  Condition Code           ????         (Indeterminate)
5777  Stack Top                000          Empty stack
5778  Interrupt Request        0            No interrupt
5779  Exception Flags          000000       No exceptions
5781 Tag Word
5782  Tags                     11           Empty
5784 Registers                 N.C.         Not changed
5786 Exception Pointers
5787  Instruction Code         N.C.         Not changed
5788  Instruction Address      N.C.         Not changed
5789  Operand Address          N.C.         Not changed
5792 Handling Numeric Processing Exceptions
5793 Once the 80287 has been initialized and normal execution of applications
5794 has been commenced, the 80287 NPX may occasionally require attention in
5795 order to recover from numeric processing errors. This section provides
5796 details for writing software exception handlers for numeric exceptions.
5797 Numeric processing exceptions have already been introduced in previous
5798 sections of this manual.
5800 As discussed previously, the 80287 NPX can take one of two actions when it
5801 recognizes a numeric exception:
5803   Ž  If the exception is masked, the NPX will automatically perform its own
5804      masked exception response, correcting the exception condition according
5805      to fixed rules, and then continuing with its instruction execution.
5807   Ž  If the exception is unmasked, the NPX signals the exception to the
5808      80286 CPU using the ERROR status line between the two processors.
5809      Each time the 80286 encounters an ESC or WAIT instruction in its
5810      instruction stream, the CPU checks the condition of this ERROR
5811      status line. If ERROR is active, the CPU automatically traps to
5812      Interrupt vector #16, the Processor Extension Error trap.
5814 Interrupt vector #16 typically points to a software exception handler,
5815 which may or may not be a part of systems software. This exception handler
5816 takes the form of an 80286 interrupt procedure.
5818 When handling numeric errors, the CPU has two responsibilities:
5820   Ž  The CPU must not disturb the numeric context when an error is
5821      detected.
5823   Ž  The CPU must clear the error and attempt recovery from the error.
5825 Although the manner in which programmers may treat these responsibilities
5826 varies from one implementation to the next, most exception handlers will
5827 include these basic steps:
5829   Ž  Store the NPX environment (control, status, and tag words, operand and
5830      instruction pointers) as it existed at the time of the exception.
5832   Ž  Clear the exception bits in the status word.
5834   Ž  Enable interrupts on the CPU.
5836   Ž  Identify the exception by examining the status and control words in
5837      the save environment.
5839   Ž  Take some system-dependent action to rectify the exception.
5841   Ž  Return to the interrupted program and resume normal execution.
5843 It should be noted that the NPX exception pointers contained in the stored
5844 NPX environment will take different forms, depending on whether the NPX is
5845 operating in Real-Address mode or in Protected mode. The earlier discussion
5846 of Real versus Protected mode details how this information is presented in
5847 each of the two operating modes.
5850 Simultaneous Exception Response
5851 In cases where multiple exceptions arise simultaneously, the 80287 signals
5852 one exception according to the precedence sequence shown in table 3-2. This
5853 means, for example, that zero divided by zero will result in an invalid
5854 operation, and not a zero divide exception.
5857 Exception Recovery Examples
5858 Recovery routines for NPX exceptions can take a variety of forms. They can
5859 change the arithmetic and programming rules of the NPX. These changes may
5860 redefine the default fix-up for an error, change the appearance of the NPX
5861 to the programmer, or change how arithmetic is defined on the NPX.
5863 A change to an error response might be to automatically normalize all
5864 denormals loaded from memory. A change in appearance might be extending the
5865 register stack into memory to provide an "infinite" number of numeric
5866 registers. The arithmetic of the NPX can be changed to automatically extend
5867 the precision and range of variables when exceeded. All these functions can
5868 be implemented on the NPX via numeric errors and associated recovery
5869 routines in a manner transparent to the application programmer.
5871 Some other possible system-dependent actions, mentioned previously, may
5872 include:
5874   Ž  Incrementing an exception counter for later display or printing
5876   Ž  Printing or displaying diagnostic information (e.g., the 80287
5877      environment and registers)
5879   Ž  Aborting further execution
5881   Ž  Storing a diagnostic value (a NaN) in the result and continuing with
5882      the computation
5884 Notice that an exception may or may not constitute an error, depending on
5885 the implementation. Once the exception handler corrects the error condition
5886 causing the exception, the floating-point instruction that caused the
5887 exception can be restarted, if appropriate. This cannot be accomplished
5888 using the IRET instruction, however, because the trap occurs at the ESC or
5889 WAIT instruction following the offending ESC instruction. The exception
5890 handler must obtain from the NPX the address of the offending instruction in
5891 the task that initiated it, make a copy of it, execute the copy in the
5892 context of the offending task, and then return via IRET to the current CPU
5893 instruction stream.
5895 In order to correct the condition causing the numeric exception, exception
5896 handlers must recognize the precise state of the NPX at the time the
5897 exception handler was invoked, and be able to reconstruct the state of the
5898 NPX when the exception initially occurred. To reconstruct the state of the
5899 NPX, programmers must understand when, during the execution of an NPX
5900 instruction, exceptions are actually recognized.
5902 Invalid operation, zero divide, and denormalized exceptions are detected
5903 before an operation begins, whereas overflow, underflow, and precision
5904 exceptions are not raised until a true result has been computed. When a
5905 before exception is detected, the NPX register stack and memory have
5906 not yet been updated, and appear as if the offending instructions has not
5907 been executed.
5909 When an after exception is detected, the register stack and memory appear
5910 as if the instruction has run to completion; i.e., they may be updated.
5911 (However, in a store or store-and-pop operation, unmasked over/underflow is
5912 handled like a before exception; memory is not updated and the stack is not
5913 popped.) The programming examples contained in Chapter Four include an
5914 outline of several exception handlers to process numeric exceptions for the
5915 80287.
5918 Table 3-2. Precedence of NPX Exceptions
5920 Signaled First:       Denormalized operand (if unmasked)
5921                       Invalid operation
5922                       Zero divide
5923                       Denormalized (if masked)
5924                       Over/Underflow
5925 Signaled Last:        Precision
5928 Chapter 4  Numeric Programming Examples
5930 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
5932 The following sections contain examples of numeric programs for the 80287
5933 NPX written in ASM286. These examples are intended to illustrate some of the
5934 techniques for programming the 80287 computing system for numeric
5935 applications.
5938 Conditional Branching Examples
5939 As discussed in Chapter Two, several numeric instructions post their
5940 results to the condition code bits of the 80287 status word. Although there
5941 are many ways to implement conditional branching following a comparison, the
5942 basic approach is as follows:
5944   Ž  Execute the comparison.
5946   Ž  Store the status word. (80287 allows storing status directly into AX
5947      register.)
5949   Ž  Inspect the condition code bits.
5951   Ž  Jump on the result.
5953 Figure 4-1 is a code fragment that illustrates how two memory-resident long
5954 real numbers might be compared (similar code could be used with the FTST
5955 instruction). The numbers are called A and B, and the comparison is A to B.
5957 The comparison itself requires loading A onto the top of the 80287 register
5958 stack and then comparing it to B, while popping the stack with the same
5959 instruction. The status word is then written into the 80286 AX register.
5961 A and B have four possible orderings, and bits C3, C2, and C0 of the
5962 condition code indicate which ordering holds. These bits are positioned in
5963 the upper byte of the NPX status word so as to correspond to the CPU's zero,
5964 parity, and carry flags (ZF, PF, and CF), when the byte is written into the
5965 flags. The code fragment sets ZF, PF, and CF of the CPU status word to the
5966 values of C3, C2, and C0 of the NPX status word, and then uses the CPU
5967 conditional jump instructions to test the flags. The resulting code is
5968 extremely compact, requiring only seven instructions.
5970 The FXAM instruction updates all four condition code bits. Figure 4-2 shows
5971 how a jump table can be used to determine the characteristics of the value
5972 examined. The jump table (FXAM_TBL) is initialized to contain the 16-bit
5973 displacement of 16 labels, one for each possible condition code setting.
5974 Note that four of the table entries contain the same value, because four
5975 condition code settings correspond to "empty."
5977 The program fragment performs the FXAM and stores the status word. It then
5978 manipulates the condition code bits to finally produce a number in register
5979 BX that equals the condition code times 2. This involves zeroing the unused
5980 bits in the byte that contains the code, shifting C3 to the right so that
5981 it is adjacent to C2, and then shifting the code to multiply it by 2. The
5982 resulting value is used as an index that selects one of the displacements
5983 from FXAM_TBL (the multiplication of the condition code is required because
5984 of the 2-byte length of each value in FXAM_TBL). The unconditional JMP
5985 instruction effectively vectors through the jump table to the labelled
5986 routine that contains code (not shown in the example) to process each
5987 possible result of the FXAM instruction.
5990 Figure 4-1.  Conditional Branching for Compares
5992             .
5993             .
5994             .
5995   A         DQ        ?
5996   B         DQ        ?
5997             .
5998             .
5999             .
6000             FLD       A         ; LOAD A ONTO TOP OF 287 STACK
6001             FCOMP     B         ; COMPARE A:B, POP A
6002             FSTSW     AX        ; STORE RESULT TO CPU AX REGISTER
6003             ;
6004             ; CPU AX REGISTER CONTAINS CONDITION CODES (RESULTS OF
6005             ; COMPARE)
6006             ;   LOAD CONDITION CODES INTO CPU FLAGS
6007             SAHF
6008             ;
6009             ; USE CONDITIONAL JUMPS TO DETERMINE ORDERING OF A TO B
6010             ;
6011             JP        A_B_UNORDERED       ; TEST C2 (PF)
6012             JB        A_LESS              ; TEST C0 (CF)
6013             JE        A_EQUAL             ; TEST C3 (ZF)
6014   A_GREATER:                    ; C0 (CF)  =  0, C3 (ZF) = 0
6015             .
6016             .
6017   A_EQUAL:                      ; C0 (CF)  =  0, C3 (ZF) = 1
6018             .
6019             .
6020   A_LESS:                       ; C0 (CF)  =  1, C3 (ZF) = 0
6021             .
6022             .
6023   A_B_UNORDERED:                ; C2 (PF) = 1
6024             .
6025             .
6028 Figure 4-2.  Conditional Branching for FXAM
6030             ; JUMP TABLE FOR EXAMINE ROUTINE
6031             ;
6032   FXAM_TBL  DW POS_UNNORM, POS_NAN, NEG_UNNORM, NEG_NAN,
6033   &             POS_NORM, POS_INFINITY, NEG_NORM,
6034   &             NEG_INFINITY, POS_ZERO, EMPTY, NEG_ZERO,
6035   &             EMPTY, POS_DENORM, EMPTY, NEG_DENORM, EMPTY
6036             .
6037             .
6038             ;  EXAMINE ST AND STORE RESULT (CONDITION CODES)
6039             FXAM
6040             FSTSW AX
6041             ;
6042             ;  CALCULATE OFFSET INTO JUMP TABLE
6043             MOV       BH,0      ; CLEAR UPPER HALF OF BX,
6044             MOV       BL,AH     ; LOAD CONDITION CODE INTO BL
6045             AND       BL,00000111B    ; CLEAR ALL BITS EXCEPT C2-C0
6046             AND       AH,01000000B    ; CLEAR ALL BITS EXCEPT C3
6047             SHR       AH,2      ;  SHIFT C3 TWO PLACES RIGHT
6048             SAL       BX,1      ;  SHIFT C2-C0 1 PLACE LEFT (MULTIPLY
6049                                 ;  BY 2)
6050             OR        BL,AH     ;  DROP C3 BACK IN ADJACENT TO C2
6051                                 ;  (000XXXX0)
6052             ;
6053             ;  JUMP TO THE ROUTINE `ADDRESSED' BY CONDITION CODE
6054             JMP       FXAM_TBL[BX]
6055             ;
6056             ;  HERE ARE THE JUMP TARGETS, ONE TO HANDLE
6057             ;    EACH POSSIBLE RESULT OF FXAM
6058   POS_UNNORM:
6059             .
6060   POS_NAN:
6061             .
6062   NEG_UNNORM:
6063             .
6064   NEG_NAN:
6065             .
6066   POS_NORM:
6067             .
6068   POS_INFINITY:
6069             .
6070   NEG_NORM:
6071             .
6072   NEG_INFINITY:
6073             .
6074   POS_ZERO:
6075             .
6076   EMPTY:
6077             .
6078   NEG_ZERO:
6079             .
6080   POS_DENORM:
6081             .
6082   NEG_DENORM:
6085 Exception Handling Examples
6086 There are many approaches to writing exception handlers. One useful
6087 technique is to consider the exception handler procedure as consisting of
6088 "prologue," "body," and "epilogue" sections of code. (For compatibility with
6089 the 80287 emulators, this procedure should be invoked by interrupt pointer
6090 (vector) number 16.)
6092 At the beginning of the prologue, CPU interrupts have been disabled. The
6093 prologue performs all functions that must be protected from possible
6094 interruption by higher-priority sources. Typically, this will involve saving
6095 CPU registers and transferring diagnostic information from the 80287 to
6096 memory. When the critical processing has been completed, the prologue may
6097 enable CPU interrupts to allow higher-priority interrupt handlers to preempt
6098 the exception handler.
6100 The exception handler body examines the diagnostic information and makes a
6101 response that is necessarily application-dependent. This response may range
6102 from halting execution, to displaying a message, to attempting to repair the
6103 problem and proceed with normal execution.
6105 The epilogue essentially reverses the actions of the prologue, restoring
6106 the CPU and the NPX so that normal execution can be resumed. The epilogue
6107 must not load an unmasked exception flag into the 80287 or another exception
6108 will be requested immediately.
6110 Figures 4-3, 4-4 and 4-5 show the ASM286 coding of three skeleton
6111 exception handlers. They show how prologues and epilogues can be written for
6112 various situations, but provide comments indicating only where the
6113 application-dependent exception handling body should be placed.
6115 Figure 4-3 and 4-4 are very similar; their only substantial difference is
6116 their choice of instructions to save and restore the 80287. The tradeoff
6117 here is between the increased diagnostic information provided by FNSAVE and
6118 the faster execution of FNSTENV. For applications that are sensitive to
6119 interrupt latency or that do not need to examine register contents, FNSTENV
6120 reduces the duration of the "critical region," during which the CPU will
6121 not recognize another interrupt request (unless it is a nonmaskable
6122 interrupt).
6124 After the exception handler body, the epilogues prepare the CPU and the NPX
6125 to resume execution from the point of interruption (i.e., the instruction
6126 following the one that generated the unmasked exception). Notice that the
6127 exception flags in the memory image that is loaded into the 80287 are
6128 cleared to zero prior to reloading (in fact, in these examples, the entire
6129 status word image is cleared).
6131 The examples in figures 4-3 and 4-4 assume that the exception handler
6132 itself will not cause an unmasked exception. Where this is a possibility,
6133 the general approach shown in figure 4-5 can be employed. The basic
6134 technique is to save the full 80287 state and then to load a new control
6135 word in the prologue. Note that considerable care should be taken when
6136 designing an exception handler of this type to prevent the handler from
6137 being reentered endlessly.
6140 Figure 4-3.  Full-State Exception Handler
6142   SAVE_ALL            PROC
6143   ;
6144   ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR 80287 STATE IMAGE
6145             PUSH      BP
6146             MOV       BP,SP
6147             SUB       SP,94
6148   ; SAVE FULL 80287 STATE, WAIT FOR COMPLETION, ENABLE CPU INTERRUPTS
6149             FNSAVE    [BP-94]
6150             FWAIT
6151             STI
6152   ;
6153   ; APPLICATION-DEPENDENT EXCEPTION HANDLING CODE GOES HERE
6154   ;
6155   ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED STATE IMAGE
6156             MOV       BYTE PTR [BP-92], 0H
6157             FRSTOR    [BP-94]
6158   ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
6159             MOV       SP,BP
6160             .
6161             .
6162             POP       BP
6163   ;
6164   ; RETURN TO INTERRUPTED CALCULATION
6165             IRET
6166   SAVE_ALL            ENDP
6169 Figure 4-4.  Reduced-Latency Exception Handler
6171   SAVE_ENVIRONMENT PROC
6172   ;
6173   ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR 80287 ENVIRONMENT
6174             PUSH      BP
6175             .
6176             MOV       BP,SP
6177             SUB       SP,14
6178   ; SAVE ENVIRONMENT, WAIT FOR COMPLETION, ENABLE CPU INTERRUPTS
6179             FNSTENV   [BP-14]
6180             FWAIT
6181             STI
6182   ;
6183   ; APPLICATION EXCEPTION-HANDLING CODE GOES HERE
6184   ;
6185   ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED
6186   ; ENVIRONMENT IMAGE
6187             MOV       BYTE PTR [BP-12], 0H
6188             FLDENV    [BP-14]
6189   ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
6190             MOV       SP,BP
6191             POP       BP
6192   ;
6193   ; RETURN TO INTERRUPTED CALCULATION
6194             IRET
6195   SAVE_ENVIRONMENT ENDP
6198 Figure 4-5.  Reentrant Exception Handler
6200             .
6201             .
6202             .
6203          LOCAL_CONTROL  DW  ?  ; ASSUME INITIALIZED
6204             .
6205             .
6206             .
6207   REENTRANT           PROC
6208   ;
6209   ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR
6210   ; 80287 STATE IMAGE
6211          PUSH     BP
6212             .
6213             .
6214             .
6215         MOV       BP,SP
6216         SUB       SP,94
6217   ; SAVE STATE, LOAD NEW CONTROL WORD, FOR COMPLETION, ENABLE CPU
6218   ; INTERRUPTS
6219         FNSAVE    [BP-94]
6220         FLDCW     LOCAL_CONTROL
6221         STI
6222             .
6223             .
6224             .
6225   ; APPLICATION EXCEPTION HANDLING CODE GOES HERE.
6226   ; AN UNMASKED EXCEPTION GENERATED HERE WILL CAUSE THE EXCEPTION
6227   ; HANDLER TO BE REENTERED.
6228   ; IF LOCAL STORAGE IS NEEDED, IT MUST BE ALLOCATED ON THE CPU STACK.
6229             .
6230             .
6231             .
6232   ; CLEAR EXCEPTION FLAGS IN STATUS WORD RESTORE MODIFIED STATE IMAGE
6233         MOV       BYTE PTR [BP-92], 0H
6234         FRSTOR    [BP-94]
6235   ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS
6236         MOV       SP,BP
6237             .
6238             .
6239             .
6240         POP       BP
6241   ; RETURN TO POINT OF INTERRUPTION
6242         IRET
6243   REENTRANT           ENDP
6246 Floating-Point to ASCII Conversion Examples
6247 Numeric programs must typically format their results at some point for
6248 presentation and inspection by the program user. In many cases, numeric
6249 results are formatted as ASCII strings for printing or display. This example
6250 shows how floating-point values can be converted to decimal ASCII character
6251 strings. The function shown in figure 4-6 can be invoked from PL/M-286,
6252 Pascal-286, FORTRAN-286, or ASM286 routines.
6254 Shortness, speed, and accuracy were chosen rather than providing the
6255 maximum number of significant digits possible. An attempt is made to keep
6256 integers in their own domain to avoid unnecessary conversion errors.
6258 Using the extended precision real number format, this routine achieves a
6259 worst case accuracy of three units in the 16th decimal position for a
6260 noninteger value or integers greater than 10^(18). This is double precision
6261 accuracy. With values having decimal exponents less than 100 in magnitude,
6262 the accuracy is one unit in the 17th decimal position.
6264 Higher precision can be achieved with greater care in programming, larger
6265 program size, and lower performance.
6268 Figure 4-6.  Floating-Point to ASCII Conversion Routine
6270 iAPX286 MACRO ASSEMBLER   80287 Floating-Point to 18-Digit ASCII Conversion          10:12:38  09/25/83  PAGE    1
6272 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE FLOATING_TO_ASCII
6273 OBJECT MODULE PLACED IN :F3:FPASC.OBJ
6274 ASSEMBLER INVOKED BY:  ASM286.86 :F3:FPASC.AP2
6276 LOC  OBJ           LINE       SOURCE
6278                       1  +1   $title("80287 Floating-Point to 18-Digit ASCII Conversion")
6279                       2
6280                       3                       name    floating_to_ascii
6281                       4
6282                       5                       public  floating_to_ascii
6283                       6                       extrn   get_power_IO near.tos_status near
6284                       7       ;
6285                       8       ;        This subroutine will convert the floating point number in the
6286                       9       ;        top of the 80287 stack to an ASCII string and separate power of 10
6287                      10       ;        scaling value (in binary).  The maximum width of the ASCII string
6288                      11       ;        formed is controlled by a parameter which must be > 1.  Unnormal values,
6289                      12       ;        denormal values, and psuedo zeroes will be correclty converted.
6290                      13       ;        A returned value will indicate how many binary bits of
6291                      14       ;        precision were lost in an unnormal or denormal value.  The magnitude
6292                      15       ;        (in terms of binary power) of a psuedo zero will also be indicated.
6293                      16       ;        Integers less than 10**18 in magnitude are accurately converted if the
6294                      17       ;        destination ASCII string field is wide enough to hold all the
6295                      18       ;        digits.  Otherwise the value is converted to scientific notation.
6296                      19       ;
6297                      20       ;          The status of the conversion is identified by the return value,
6298                      21       ;        it can be:
6299                      22       ;
6300                      23       ;                0       conversion complete, string_size is defined
6301                      24       ;                1       invalid arguments
6302                      25       ;                2       exact integer conversion, string_size is defined
6303                      26       ;                3       indefinite
6304                      27       ;                4       + NAN (Not A Number)
6305                      28       ;                5       - NAN
6306                      29       ;                6       + Infinity
6307                      30       ;                7       - Infinity
6308                      31       ;                8       psuedo zero found, string_size is defined
6309                      32       ;
6310                      33       ;            The PLM/286 calling convention is
6311                      34       ;
6312                      35       ;floating_to_ascii:
6313                      36       ;        procedure (number,denormal ptr, string ptr, size_ptr, field_size,
6314                      37       ;                power_ptr) word external.
6315                      38       ;        declare (denormal_ptr, string ptr, power ptr, size_ptr) pointer,
6316                      39       ;        declare field_size word, string_size basd size_ptr word,
6317                      40       ;        delcare number real;
6318                      41       ;        declare denormal integer based denormal_ptr,
6319                      42       ;        declare power integer based power_ptr,
6320                      43       ;        and floating_to_ascii,
6321                      44       ;
6322                      45       ;          The floating point value is expected to be on the top of the NPX
6323                      46       ;        stack.  This subroutine expects 3 free entries on the NPX stack and
6324                      47       ;        will pop the passed value off when done.  The generated ASCII string
6325                      48       ;        will have a leading character either '-' or '+' indicating the sign
6326                      49       ;        of the value.  The ASCII decimal digits will immediately follow.
6327                      50       ;        The numeric value of the ASCII string is (ASCII STRING )*10**POWER.
6328                      51       ;        If the given number was zero, the ASCII string will contain a sign
6329                      52       ;        and a single zero character.  The value string_size indicates the total
6330                      53       ;        length of the ASCII string including the sign character.  String(0) will
6331                      54       ;        always hold the sign.  It is possible for string_size to be less than
6332                      55       ;        field_size.  This occurs for zeroes or integer values.  A psuedo zero
6333                      56       ;        will return a special return code.  The denormal count will indicate
6334                      57       ;        the power of the two originally associated with the value.  The power of
6335                      58       ;        ten and ASCII string will be as if the value was an ordinary zero.
6336                      59       ;
6337                      60       ;          The subroutine is accurate up to a maximum of 18 decimal digits for
6338                      61       ;        integers.  Integer values will have a decimal power of zero associated
6339                      62       ;        with them.  For non-integers, the result will be accurate to within 2
6340                      63       ;        decimal digits of the 16th decimal place (double pracision).  The
6341                      64       ;        exponentiate instruction is also used for scaling the value into the
6342                      65       ;        range acceptable for the BCD data type.  The rounding mode in effect
6343                      66       ;        on entry to the subroutine is used for the conversion.
6344                      67       ;
6345                      68       ;          The following registers are not tranparent
6346                      69       ;
6347                      70       ;                ax bx cx dx si di flags
6348                      71       ;
6349                      72  +1  $eject
6350                      73       ;
6351                      74       ;           Define the stack layout
6352                      75       ;
6353  0000[]              76       bp_save     equ     word ptr [bp]
6354  0002[]              77       es_save     equ     bp_save + size bp_save
6355  0004[]              78       return_ptr  equ     es_save + size es_save
6356  0006[]              79       power_ptr   equ     return_ptr _ size return_ptr
6357  0008[]              80       field_size  equ     power_ptr + size power_ptr
6358  000A[]              81       size_ptr    equ     field_size + size field_size
6359  000C[]              82       string_ptr  equ     size_ptr + size size_ptr
6360  000E[]              83       denormal_ptr    equ     string_ptr + size string_ptr
6361                      84
6362                      85       parms_size  equ     size power_ptr + size field_size + size_ptr +
6363  000A                86       &                   size string_ptr + size denormal_ptr
6364                      87
6365                      88                   Define constants used
6366                      89
6367  0012                90       BCD_DIGIIS  equ     18          ; Number of digits in bcd_value
6368  0002                91       WORD-SIZE   equ     2
6369  000A                92       BCD_SIZE    equ     10
6370  0001                93       MINUS       equ     1           ; Define return values
6371  0004                94       NAN         equ     4           ; The exact values chosen here are
6372  0006                95       INFINITY    equ     6           ; important.  They must correspond to
6373  0003                96       INDEFINITE  equ     3           ; the possible return values and be in
6374  0008                97       PSUEDO_ZERO equ     8           ; the same numeric order as tested by
6375 -0002                98       INVALID     equ     -2          ; the program.
6376 -0004                99       ZERO        equ     -4
6377 -0006               100       DENORMAL    equ     -6
6378  0008               101       UNNORMAL    equ     -8
6379  0000               102       NORMAL      equ     0
6380  0002               103       EXACT       equ     2
6381                     104       ;
6382                     105       ;           Define layout of temporary storage area
6383                     106       ;
6384 -0002[]             107       status      equ     word ptr [bp-WORD_SIZE]
6385 -0004[]             108       power_two   equ     status - WORD_SIZE
6386 -0006[]             109       power_ten   equ     power_two - WORD_SIZE
6387 -0010[]             110       bcd_value   equ     tbyte ptr power_ten - BCD_SIZE
6388 -0010[]             111       bcd_byte    equ     byte ptr bcd_value
6389 -0010[]             112       fraction    equ     bcd_value
6390                     113
6391                     114       local_size  equ     size status + size pwer_two + size power_ten
6392  0010               115       &                   + size bcd_value
6393                     116
6394 ----                117       stack       stackseg (local_size+6) ; Allocate stack space for locals
6395                     118   +1  $eject
6396 ----                119       code        segment or public
6397                     120                   extrn   power_table:qword
6398                     121       ;
6399                     122       ;           Constants used by this function
6400                     123       ;
6401                     124                       even                ; Optimize for 16 bits
6402 0000 0A00           125       const10         dw      10          ; Adjustment value for too big BCD
6403                     126       ;
6404                     127       ;         Convert the C3,C2,C1,C0 encoding from tos_status into meaningful bit
6405                     128       ;       flags and values.
6406                     129       ;
6407 0002 F8             130       status_table    db  UNNORMAL, NAN, UNNORMAL + MINUS, NAN + MINUS
6408 0003 04
6409 0004 F9
6410 0005 05
6411 0006 00             131       &                   NORMAL, INFINITY, NORMAL + MINUS, INFINITY + MINUS
6412 0007 06
6413 0008 01
6414 0009 07
6415 000A FC             132       &                   ZERO, INVALID, ZERO + MINUS, INVALID
6416 000B FE
6417 000C FD
6418 000D FE
6419 000E FA             133       &                   DENORMAL, INVALID, DENORMAL + MINUS, INVALID
6420 000F FE
6421 0010 FB
6422 0011 FE
6423                     134
6424 0012                135       floating_to_ascii proc
6425                     136
6426 0012 E80000         137               call    tos_status              ; look at status of ST(0)
6427 0015 8BD8           138               mov     bx,ax                   ; Get descriptor from table
6428 0017 2E8A870200     139               mov     al,status_table[bx]
6429 001C 3CFE           140               cmp     al,INVALID              ; Look for empty ST(0)
6430 001E 752B           141               jne     not_empty
6431                     142       ;
6432                     143       ;        ST(0) is empty!  Return the status value
6433                     144       ;
6434 0020 C20A00         145               ret     parms_size
6435                     146       ;
6436                     147       ;         Remove infinity from stack and exit
6437                     148       ;
6438 0023                149       found_infinity
6439                     150
6440 0023 DDD8           151               fstp    st(0)                   ; OR to leave fstp running
6441 0025 EB02           152               jmp     short exit_proc
6442                     153       ;
6443                     154       ;         String space is too small!  Return invalid code
6444                     155       ;
6445 0027                156       small_string
6446                     157
6447 0027 B0FE           158               mov     al,INVALID
6448                     159
6449 0029                160       exit_proc:
6450                     161
6451 0029 C9             162               leave                           ; Restore stack
6452 002A 07             163               pop     es
6453 002B C20A00         164               ret     parms_size
6454                     165       ;
6455                     166       ;         ST(0) is NAN or indefinite.  Store the value in memory and look
6456                     167       ;       at the fraction field to separate indefinite from an ordinary NAN.
6457                     168       ;
6458 002E                169       NAN_or_indefinite:
6459 002E DB7EF0         170
6460 0031 A801           171               fstp    fraction                ; Remove value from stack for examination
6461 0033 9B             172               test    al,MINUS                ; Look at sign bit
6462 0034 74F3           173               fwait                           ; Insure store is done
6463                     174               jz      exit_proc               ; Can't be indefinite if positive
6464 0036 BB00C0         175
6465 0039 2B5EF6         176               mov     bx,0C000H               ; Match against upper 16 bits of fraction
6466 003C 0B5EF4         177               sub     bx,word ptr fraction+6  ; Compare bits 63-4B
6467 003F 0B5EF2         178               or      bx,word ptr fraction+4  ; Bits 32-47 must be zero
6468 0042 0B5EF0         179               or      bx,word ptr fraction+2  ; Bits 31-16 must be zero
6469 0045 75E2           180               or      bx,word ptr fraction    ; Bits 15-0 must be zero
6470                     181               jnz     exit_proc
6471 0047 B003           182
6472 0049 EBDE           183               mov     al,INDEFINITE           ; Set return value for indefinite value
6473                     184               jmp     exit_proc
6474                     185       ;
6475                     186       ;         Allocate stack space for local variables and establish parameter
6476                     187       ;       addressibility.
6477                     188       ;
6478 004B                189       not_empty:
6479                     190
6480 004B 06             191               push    es                      ; Save working register
6481 004C C8100000       192               enter   local_size,0            ; Format stack
6482                     193
6483 0050 8B4E08         194               mov     cx,field_ize            ; Check for enough string space
6484 0053 83F902         195               cmp     cx,2
6485 0056 7CCF           196               jl      sjall_string
6486                     197
6487 005B 49             198               dec     cx                      ; Adjust for sign character
6488 0059 83F912         199               cmp     cx,BCD_DIGITS           ; See if string is too large for BCD
6489 005C 7603           200               jbe     size_ok
6490                     201
6491 005E B91200         202               mov     cx,BCD_DIGITS           ; Else set maximum string size
6492                     203
6493 0061                204       size_ok:
6494                     205
6495 0061 3C06           206               cmp     al,INFINITY             ; Look for infinity
6496 0063 7DBE           207               jge     found_infinity          ; Return status value for + or - inf
6497                     208
6498 0065 3C04           209               cmp     al,NAN                  ; Look for NAN or INDEFINITE
6499 0067 7DC5           210               jge     NAN_or_indefinite
6500                     211       ;
6501                     212       ;         Set default return values and check that the number is normalized
6502                     213       ;
6503 0069 D9E1           214               fabs                            ; Use positive value only
6504                     215                                               ; sign bit in al has true sign of value
6505 006B 8BD0           216               mov     dx,ax                   ; Save return value for later
6506 006D 33C0           217               xor     ax,ax                   ; Form 0 constant
6507 006F 8B7E0E         218               mov     di,denormal_ptr         ; Zero denormal count
6508 0072 8905           219               mov     word ptr [di],ax
6509 0074 8B5E06         220               mov     bx,power_ptr            ; Zero power of ten value
6510 0077 B907           221               mov     word ptr [bx],ax
6511 0079 80FAFC         222               cmp     dl,ZERO                 ; Test for zero
6512 007C 732B           223               jae     real_zero               ; Skip power code if value is zero
6513                     224
6514 007E 80FAFA         225               cmp     dl,DENORMAL             ; Look for a denormal value
6515 008A 732C           226               jae     found_denormal          ; Handle it specially
6516                     227
6517 0083 D9F4           228               fxtract                         ; Separate exponent from signifand
6518 0085 80FAF8         229               cmp     dl,UNNORMAL             ; Test for unnormal value
6519 0088 7240           230               jb      normal_value
6520                     231
6521 008A 80EAF8         232               sub     dl,UNNORMAL-NORMAL      ; Return normal status with correct sign
6522                     233       ;
6523                     234       ;         Normalize the fraction, adjust the power of two in ST(1) and set
6524                     235       ;       the denormal count value
6525                     236       ;
6526                     237       ;       Assert 0 <= ST(0) < 1.0
6527                     238       ;
6528 008D D9E8           239               fld1                            ; Load constant to normalize fraction
6529                     240
6530 008F                241       normalize_fraction
6531                     242
6532 008F DCC1           243               fadd    st(1),st                ; Set integer bit in fraction
6533 0091 DEE9           244               fsub                            ; Form normalized fraction in ST(0)
6534 0093 D9F4           245               fxtract                         ; Power of two field will be negative
6535                     246                                               ; of denormal count
6536 0095 D9C9           247               fxch                            ; Put denormal count in ST(0)
6537 0097 DF15           248               fist    word ptr [di]           ; Put negative of denormal count in memory
6538 0099 DEC2           249               faddp   st(2),st                ; Form correct power of two in st(1)
6539                     250                                               ; OK to use word ptr [di] now
6540 009B F71D           251               neg     word ptr [di]           ; Form positive denormal count
6541 009D 752B           252               jnz     not_psuedo_zero
6542                     253       ;
6543                     254       ;         A psuedo zero will appear as an unnormal number.  When attempting
6544                     255       ;       to normalize it, the resultant fraction field will be zero.  Performing
6545                     256       ;       an fxtract on zero will yield a zero exponent value.
6546                     257       ;
6547 009F D9C9           258               fxch                        ; Put power of two value in st(0)
6548 00A1 DF1D           259               fistp   wrd ptr [di]        ; Set denormal count ot power of two value.
6549                     260                                           ; Word ptr [di] is not used by convert
6550                     261                                           ; integer, OK to leave running
6551 00A3 B0EAF8         262               sub     dl,NORMAL-PSUEDO_ZERO ; Set return value saving the sign bit
6552 00A6 E9A400         263               jmp     convert_integer     ; Put zero value into memory
6553                     264       ;
6554                     265       ;         The number is a real zero, set the return value and setup for
6555                     266       ;       conversion to BCD.
6556                     267       ;
6557 00A9                268       real_zero
6558                     269
6559 00A9 80EAF0         270               sub     dl,ZERO-NORMAL          ; Convert status to normal value
6560 00AC E99E00         271               jmp     convert_integer         ; Treat the zero as an integer
6561                     272       ;
6562                     273       ;         The number is a denormal.  FXTRACT will not work correctly in this
6563                     274       ;       case.  To correctly separate the exponent and fraction, add a fixed
6564                     275       ;       constant to the exponent to guarantee the rsult is not a denormal.
6565                     276       ;
6566 00AF                277       found_denormal:
6567                     278
6568 00AF D9E8           279               fld1                            ; Prepare to bump exponent
6569 00B1 D9C9           280               fxch
6570 00B3 D9F8           281               fprem                           ; Force denormal to smallest representable
6571                     282                                               ; extended real format exponent
6572 00B5 D9F4           283               fxtract                         ; This will work correctly now
6573                     284       ;
6574                     285       ;         The power of the original enormal value has been safely isolated.
6575                     286       ;       Check if the fraction value is an unnormal.
6576                     287       ;
6577 00B7 D9E5           288               fxam                            ; See if the fraction is an unnormal
6578 00B9 9BDFE0         289               fstsw   ax                      ; Save 80287 status in CPU AX reg for later
6579 00BC D9C9           290               fxch                            ; Put exponent in ST(0)
6580 00BE D9CA           291               fxch    st(2)                   ; Put 1.0 into ST(0), exponent in ST(2)
6581 00C0 80EAFA         292               sub     dl,DENORMAL-NORMAL      ; Return normal status with correct sign
6582 00C3 A90044         293               test    ax,4400H                ; See if C0=C2=0 impling unnormal or NAN
6583 00C6 74C7           294               jz      normalize_fraction      ; Jump if fraction is an unnormal
6584                     295
6585 00C8 DDD8           296               fstp    st(0)                   ; Remove unnecessary 1.0 from st(0)
6586                     297       ;
6587                     298       ;         Calculate the decimal magnitude associated with this number to
6588                     299       ;       within one order.  This error will always be inevitable due to
6589                     300       ;       rounding and lost precision.  As a result, we will deliberately fail
6590                     301       ;       to consider the LOQ10 of the fraction value in calcuating the order.
6591                     302       ;       Since the fraction will always be 1 <= F < 2, its LOQ10 will not change
6592                     303       ;       the basic accuracy of the function.  To get the decimal order of magnitude,
6593                     304       ;       simply multiply the power of two by LOQ10(2) and truncate the result to
6594                     305       ;       an integer.
6595                     306       ;
6596 00CA                307       normal_value:
6597 00CA                308       not_pseudo_zero:
6598                     309
6599 00CA DB7EF0         310               fstp    fraction                ; Save the fraction field for later use
6600 00CD DF56FC         311               fist    power_two               ; Save power of two
6601 00D0 D9EC           312               fldlg2                          ; Get LOQ10(2)
6602                     313                                               ; Power_two is now safe to use
6603 00D2 DEC9           314               fmul                            ; Form LOQ10(of exponent of number)
6604 00D4 DF5EFA         315               fistp   power_ten               ; Any rounding mode will work here
6605                     316       ;
6606                     317       ;         Check if the magnitude of the number rules out treating it as
6607                     318       ;       an integer.
6608                     319       ;
6609                     320       ;       CX has the maximum number of decimal digits allowed.
6610                     321       ;
6611 00D7 7B             322               fwait                           ; Wait for power_ten to be valid
6612 00D8 3B46FA         323               mov     ax,power_ten            ; Get power of ten of value
6613 00DB 2BC1           324               sub     ax,cx                   ; Form scaling factor necessary in ax
6614 00DD 7722           325               ja      adjust_result           ; Jump if number will not fit
6615                     326       ;
6616                     327       ;         The number is between 1 and 10**(field_size).
6617                     328       ;       Test if it is an integer.
6618                     329       ;
6619 00DF 0F46FC         330               fild    power_two               ; Restore original number
6620 00E2 8BF2           331               mov     si,dx                   ; Save return value
6621 00E4 80EAFE         332               sub     dl,NORMAL-EXACT         ; Convert to exact return value
6622 00E7 0B6EF0         333               fld     fraction
6623 00EA 09FD           334               fscale                          ; Form full value, this is safe here
6624 00EC DDD1           335               fst     st(1)                   ; Copy value for compare
6625 00EE 09FC           336               frndint                         ; Test if its an integer
6626 00F0 08D9           337               fcomp                           ; Compare values
6627 00F2 7BDD7EFE       338               fstsw   status                  ; Save status
6628 00F6 F746FE0040     339               test    status,4000H            ; C3=1 implies it was an integer
6629 00FB 7550           340               jnz     convert_integer
6630                     341
6631 00FD DDD8           342               fstp    st(0)                   ; Remove non integer value
6632 00FF 8BD6           343               mov     dx,si                   ; Restore original return value
6633                     344       ;
6634                     345       ;         Scale the number to within the range allowed by the BCD format
6635                     346       ;       The scaling operation should produce a number within one decimal order
6636                     347       ;       of magnitude of the largest decimal number representable within the
6637                     348       ;       given string width.
6638                     349       ;
6639                     350       ;         The scaling power of ten value is in ax.
6640                     351       ;
6641 0101                352       adjust_result:
6642                     353
6643 0101 8907           354               mov     word ptr [bx],ax        ; Set initial power of ten return value
6644 0103 F7D8           355               neg     ax                      ; Substract one for each order
6645                     356                                               ; of magnitude the value is scaled by
6646 0105 E80000     E   357               call    get_power_10            ; Scaling factor is returned as exponent
6647                     358                                               ; and fraction
6648 0108 DB6EF0         359               fld     fraction                ; Get fraction
6649 010B DEC9           360               fmul                            ; Combine fractions.
6650 010D 8BF1           361               mov     si,cx                   ; Form power of ten of the maximum
6651 010F D1E6           362               shl     si,1                    ; BCD value to fit in the string
6652 0111 D1E6           363               shl     si,1                    ; Index in si
6653 0113 D1E6           364               shl     si,1
6654 0115 DF46FC         365               fild    power_two               ; Combine powers of two
6655 0118 DEC2           366               faddp   st(2),st
6656 011A D9FD           367               fscale                          ; Form full value, exponent was safe
6657 011C DDD9           368               fstp    st(1)                   ; Remove exponent
6658                     369       ;
6659                     370       ;         Test the adjusted value against a table of exact powers of ten.
6660                     371       ;       The combined errors of the magnitude estimate and power function
6661                     372       ;       result in a value one order of magnitude too small or too large to fit
6662                     373       ;       correctly in the BCD field.  To handle this problem, pretest the
6663                     374       ;       adjusted value, if it is too small or large, then adjust it by ten and
6664                     375       ;       adjust the power of ten value.
6665                     376       ;
6666 011E                377       test_power:
6667 011E 2EDC940800  E  378
6668                     379               fcom    power_table[si]_type power_table; Compare against exact power
6669                     380                                               ; entry.  Use the next entry since cx
6670                     381                                               ; has been decremented by one.
6671 0123 9BDFE0         382               fstsw   ax                      ; No wait is necessary
6672 0126 690041         383               test    ax,4100H                ; If C3 = C0 = 0 then too big
6673 0129 750C           384               jnz     text_for_small
6674                     385
6675 012B 2EDE360000  R  386               fidiv   const10                 ; Else adjust value
6676 0130 80E2FD         387               and     dl,not EXACT            ; Remove exact flag
6677 0133 FF07           388               inc     word ptr [bx]           ; Adjust power of ten value
6678 0135 EB14           389               jmp     short in_range          ; Convert the value to a BCD integer
6679                     390
6680 0137                391       test_for_small
6681                     392
6682 0137 2EDC940000  E  393               fcom    power_table[si]         ; Test relative size
6683 013C 9BDFE0         394               fstsw   ax                      ; No wait is necessary
6684 013F A90001         395               test    ax,100H                 ; If C0 = 0 then st(0) >= lower bound
6685 0142 7407           396               jz      in_range                ; Convert the value to a BCD integer
6686                     397
6687 0144 2EDE0E0000  R  398               fimul   const10                 ; Adjust value into range
6688 0149 FF0F           399               dec     word ptr [bx]           ; Adjust power of ten value
6689                     400
6690 014B                401       in_range:
6691                     402
6692 014B D9FC           403               frndint                         ; Form integer value
6693                     404       ;
6694                     405       ;       Assert: 0 <= TOS <= 999,999,999,999,999,999
6695                     406       ;       The TOS number will be exactly representable in 18 digit BCD format
6696                     407       ;
6697 014D                408       convert_integer:
6698                     409
6699 014D DF76F0         410               fbstp   bcd_value               ; Store ax BCD format number
6700                     411       ;
6701                     412       ;         While the store BCD runs, setup registers for the conversion to
6702                     413       ;       ASCII.
6703                     414       ;
6704 0150 BE0800         415               mov     si,BCD_SIZE-2           ; Initial BCD index value
6705 0153 B9040F         416               mov     cx,0f04h                ; Set shift count and mask
6706 0156 BB0100         417               mov     bx,1                    ; Set initial size of ASCII field for sign
6707 0159 8B730C         418               mov     di,string_ptr           ; Get address of start of ASCII string
6708 015C BCD8           419               mov     ax,ds                   ; Copy ds to es
6709 015E BEC0           420               mov     es,ax
6710 0160 FC             421               cld                             ; Set autoincrement mode
6711 0161 B02B           422               mov     al,'+'                  ; Clear sign field
6712 0163 F6C201         423               text    dl,MINUS                ; Look for negative value
6713 0166 7402           424               jr      positive_result
6714                     425
6715 0168 B02D           426               mov     al,'-'
6716                     427
6717 016A                428       positive_result:
6718                     429
6719 016A AA             430               stash                           ; Bump string pointer past sign
6720 016B 809E2FE        431               and     dl,not MINUS            ; Turn off sign bit
6721 016E 9B             432               fwait                           ; Wait for fbstp to finish
6722                     433       ;
6723                     434       ;         Register usage:
6724                     435       ;                               ah:     BCD byte value in use
6725                     436       ;                               al:     ASCII character value
6726                     437       ;                               dx:     Return value
6727                     438       ;                               ch:     BCD mask = ofh
6728                     439       ;                               cl      BCD shift count = 4
6729                     440       ;                               bx:     ASCII string field width
6730                     441       ;                               si:     BCD field index
6731                     442       ;                               di:     ASCII string field pointer
6732                     443       ;                               ds,es:  ASCII string segment base
6733                     444       ;
6734                     445       ;         Remove leading zeroes from the number.
6735                     446       ;
6736 016F                447       skip_leading_zeroes
6737                     448
6738 016F 8A62F0         449               move    ah,bcd_byte[si]         ; Get BCD byte
6739 0172 BAC4           450               move    al,ah                   ; Copy value
6740 0174 D2E8           451               shr     al,cl                   ; Get high order digit
6741 0176 22C5           452               and     al,ch                   ; Set zero flag
6742 0178 7516           453               jnz     enter_odd               ; Enter loop if leading non zero found
6743                     454
6744 017A 8AC4           455               mov     al,ah                   ; Get BCD byte again
6745 017C 22C5           456               and     al,ch                   ; Get low order digit
6746 017E 7518           457               jnz     enter_even
6747                     458
6748 0180 4E             459               dec     si                      ; Decrement BCD index
6749 0181 79EC           460               jns     skip_leading_zeroes
6750                     461       ;
6751                     462       ;         The significand was all zeroes
6752                     463       ;
6753 0183 B030           464               mov     al,'0'                  ; Set initial zero
6754 0185 AA             465               stosb
6755 0186 43             466               inc     bx                      ; Bump string length
6756 0187 EB16           467               jmp     short exit_with_value
6757                     468       ;
6758                     469       ;         Now expand the BCD string into digit per byte values 0-9
6759                     470       ;
6760 0189                471       digit_loop
6761                     472
6762 0189 8A62F0         473               mov     ah,bcd_byte[si]         ; Get BCD byte
6763 018C 8AC4           474               mov     al,ah
6764 018E D2E8           475               shr     al,cl                   ; Get high order digit
6765                     476
6766 0190                477       enter_odd
6767                     478
6768 0190 0430           479               add     al,'0'                  ; Convert to ASCII
6769 0192 AA             480               stosb                           ; Put digit into ASCII string area
6770 0193 8AC4           481               mov     al,ah                   ; Get low order digit
6771 0195 22C5           482               and     al,ch
6772 0197 43             483               inc     bx                      ; Bump field size counter
6773                     484
6774 0198 0430           485       enter_even
6775 019A AA             486
6776 019B 43             487               add     al,'0'                  ; Convert to ASCII
6777 019C 4E             488               stosb                           ; Put digit into ASCII area
6778 019D 79EA           489               inc     bx                      ; Bump field size counter
6779                     490               dec     si                      ; Go to next BCD byte
6780                     491               jns     digit_loop
6781                     492       ;
6782                     493       ;         Conversion complete.  Set the string size and remainder
6783                     494       ;
6784 019F                495       exit_with_value:
6785                     496
6786 019F 8B7E0A         497               move    di,size_ptr
6787 01A2 891D           498               mov     word ptr [di],bx
6788 01A4 8BC2           499               mov     ax,x                    ; Set return value
6789 01A6 E980FE         500               jmp     exit_proc
6790                     501
6791                     502       floating_to_ascii       endp
6792 ----                503       code                    ends
6793                     504                               end
6794 ASSEMBLY COMPLETE,          NO WARNINGS,    NO ERRORS
6797 iAPX286 MACRO ASSEMBLER     Calculate the value of 10**ax            12:11:08 09/25/83 PAGE  1
6799 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE GET_POWER_10
6800 OBJECT MODULE PLACED IN :F3:POW10.OBJ
6801 ASSEMBLER INVOKED BY:  ASM286.86 :F3:POW10.AP2
6803 LOC  OBJ           LINE       SOURCE
6805                       1  +1   $title("Calculate the value of 10**ax")
6806                       2       ;
6807                       3       ;         This subroutine will calculate the value of 10**ax.
6808                       4       ;       For values of 0 <= ax <19, the result will exact.
6809                       5       ;       All 80286 registers are transparent and the value is returned on
6810                       6       ;       the TOS as two numbers, exponent in ST(1) and fraction in ST(0).
6811                       7       ;       The exponent value can be larger than the largest exponent of an
6812                       8       ;       extended real format number.  Three stack entries are used.
6813                       9       ;
6814                      10                       name    get_power_10
6815                      11
6816                      12                       public  get_power_10,power_table
6817                      13
6818 ----                 14       stack           stackseg 8
6819                      15
6820 ----                 16       code            segment or public
6821                      17       ;
6822                      18       ;         Use exact values from 1:0 to 1e18
6823                      19       ;
6824                      20                       even                        ; Optimize 16 bit access
6825 0000 000000000000F0  21       power_table     dq      1.0,1e1,1e2,1e3
6826      3F
6827 0008 00000000000024
6828      40
6829 0010 00000000000059
6830      40
6831 0018 0000000000408F
6832      40
6833 0020 000000000088C3  22                       dq      1e4,1e5,1e6,1e7
6834      40
6835 0028 00000000006AF8
6836      40
6837 0030 0000000080842E
6838      41
6839 0038 00000000D01263
6840      41
6841 0040 0000000084D797  23                       dq      1e8,1e9,1e10,1e11
6842      41
6843 0048 0000000065CDCD
6844      41
6845 0050 000000205FA002
6846      42
6847 0058 000000E8764837
6848      42
6849 0060 000000A2941A6D  24                       dq      1e12,1e13,1e14,1e15
6850      42
6851 0068 000040E59C30A2
6852      42
6853 0070 0000901EC4BCD6
6854      42
6855 0078 00003426F56B0C
6856      43
6857 0080 0080E03779C341  25                       dq      1e16,1e17,1e18
6858      43
6859 0088 00A0D885573476
6860      43
6861 0090 00C84E676DC1AB
6862      43
6863 0098                 26
6864                      27       get_power_10    proc
6865 0098 3D1200          28
6866 009B 770F            29               cmp     ax,18                       ; Test for 0 <= ax < 19
6867                      30               ja      out_of_range
6868 009D 53              31
6869 009E 8BD8            32               push    bx                          ; Get working index register
6870 00A0 C1E303          33               mov     bx,ax                       ; Form table index
6871 00A3 2EDD870000    R 34               shl     bx,3
6872 00A8 5B              35               fld     power_table[bx]             ; Get exact value
6873 00A9 D9F4            36               pop     bx                          ; Restore register value
6874 00AB C3              37               fxtract                             ; Separate power and fraction
6875                      38               ret                                 ; OK to leave fxtract running
6876                      39       ;
6877                      40       ;         Calculate the value using the exponentiate instruction.
6878                      41       ;       The following relations are used:
6879                      42       ;               10**x = 2**(log2(10)*x)
6880                      43       ;               2**(I+F) = 2**I * 2**F
6881                      44       ;               if st(1) = I and st(0) = 2**F then fscale produces 2**(I+F)
6882                      45       ;
6883 00AC                 46       out_of_range:
6884                      47
6885 00AC D9E9            48               fld12t                              ; TOS = LOG2(10)
6886 00AE C8040000        49               enter   4.0                         ; Format stack
6887 00B2 8946FE          50               mov     [bp-2],ax                   ; Save power of 10 value
6888 00B5 DE4EFE          51               fimul   word ptr [bp-1]             ; TOS, x= LOG2(10)*P = LOG2(10**P)
6889 00B8 9BD97EFC        52               fstcw   word ptr [bp-4]             ; Get current control word
6890 00BC 8B46FC          53               mov     ax,word ptr [bp-4]          ; Get control word, no wait necessary
6891 00BF 25FFF3          54               and     ax,not OCOOH                ; Mask off current rounding field
6892 00C2 0D0004          55               or      ax,0400H                    ; Set round to negative infinity
6893 00C5 6746FC          56               xchg    ax,word ptr [bp-4]          ; Put new control word in memory
6894                      57                                                   ; old control word is in ax
6895 00C8 D9E8            58               fld1                                ; Set TOS = -1.0
6896 00CA D9E0            59               fchs
6897 00CC D9C1            60               fld     st(1)                           ; Copy power value in base two
6898 00CE D96EFC          61               fldcw   word ptr [bp-4]                 ; Set new control word value
6899 00D1 D9FC            62               frndint                                 ; TOS = I: -inf < I <= X, I is an integer
6900 00D3 8946FC          63               mov     word ptr [bp-4],ax              ; Restore original rounding control
6901 00D6 D96EFC          64               fldcw   word ptr [bp-4]
6902 00D9 D9CA            65               fxch    st(2)                           ; TOS = X, ST(1) = -1.0, St(2) = I
6903 00DB DBE2            66               fsub    st,st(2)                        ; TOS,F=X-I; 0 <= TOS < 1.0
6904 00DD 8B46FE          67               mov     ax,[bp-2]                       ; Restore power of ten
6905 00E0 D9FD            68               fscale                                  ; TOS = F/2: 0 <= TOS < 0.5
6906 00E2 D9F0            69               f2xm1                                   ; TOS = 2**(F/2) - 1.0
6907 00E4 C9              70               leave                                   ; Restore stack
6908 00E5 DEE1            71               fsubr                                   ; Form 2**(F/2)
6909 00E7 DCC8            72               fmul    st,st(0)                        ; Form 2**F
6910 00E9 C3              73               ret                                     ; OK to leave fmul running
6911                      74
6912                      75       get_power_10    endp
6913                      76
6914 ----                 77       code            ends
6915                      78                       end
6916 ASSEMBLY COMPLETE,        NO WARNINGS,   NO ERRORS
6919 iAPX286 MACRO ASSEMBLER   Determine TOS register contents          12:12:13 09/25/83 PAGE   1
6921 SERIES-III iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE TOS_STATUS
6922 OBJECT MODULE PLACED IN :F3:T0SST.OBJ
6923 ASSEMBLER INVOKED BY:  ASM286.86 :F3:TOSST.AP2
6925 LOC  OBJ           LINE      SOURCE
6927                       1   +1  $title("Determine TOS register contents")
6928                       2       ;
6929                       3       ;         This subroutine will return a value from 0-15 in AX corresponding
6930                       4       ;       to the contents of 80287 TOS.  All registers are transparent and no
6931                       5       ;       errors are possible.  The return value corresponds to c3,c2,c1,c0
6932                       6       ;       of FXAM instruction.
6933                       7       ;
6934                       8               name    tos_status
6935                       9
6936                      10               public  tos_status
6937                      11
6938 ----                 12       stack           stackseg 6              ; Allocate space on the stack
6939                      13
6940 ----                 14       code            segment er public
6941                      15
6942 0000                 16       tos_status      proc
6943                      17
6944 0000 D9E5            18               fxam                            ; Get register contents status
6945 0002 9BDFE0          19               fstsw   ax                      ; Get status
6946 0005 8AC4            20               mov     al,ah                   ; Put bit 10-8 into bits 2-0
6947 0007 250740          21               and     ax,4007h                ; Mask out bits c3,c2,c1,c0
6948 000A C0EC03          22               shr     ah,3                    ; Put bit c3 into bit 11
6949 000D 0AC4            23               or      al,ah                   ; Put c3 into bit 3
6950 000F B400            24               mov     ah,0                    ; Clear return value
6951 0011 C3              25               ret
6952                      26
6953                      27       tos_status      endp
6954                      28
6955 ----                 29       code            ends
6956                      30                       end
6957 ASSEMBLY COMPLETE,       NO WARNINGS,   NO ERRORS
6960 Function Partitioning
6961 Three separate modules implement the conversion. Most of the work of the
6962 conversion is done in the module FLOATING_TO_ASCII. The other modules are
6963 provided separately, because they have a more general use. One of them,
6964 GET_POWER_10, is also used by the ASCII to floating-point conversion
6965 routine. The other small module, TOS_STATUS, will identify what, if
6966 anything, is in the top of the numeric register stack.
6969 Exception Considerations
6970 Care is taken inside the function to avoid generating exceptions. Any
6971 possible numeric value will be accepted. The only exceptions possible would
6972 occur if insufficient space exists on the numeric register stack.
6974 The value passed in the numeric stack is checked for existence, type (NaN
6975 or infinity), and status (unnormal, denormal, zero, sign). The string size
6976 is tested for a minimum and maximum value. If the top of the register stack
6977 is empty, or the string size is too small, the function will return with an
6978 error code.
6980 Overflow and underflow is avoided inside the function for very large or
6981 very small numbers.
6984 Special Instructions
6985 The functions demonstrate the operation of several numeric instructions,
6986 different data types, and precision control. Shown are instructions for
6987 automatic conversion to BCD, calculating the value of 10 raised to an
6988 integer value, establishing and maintaining concurrency, data
6989 synchronization, and use of directed rounding on the NPX.
6991 Without the extended precision data type and built-in exponential function,
6992 the double precision accuracy of this function could not be attained with
6993 the size and speed of the shown example.
6995 The function relies on the numeric BCD data type for conversion from binary
6996 floating-point to decimal. It is not difficult to unpack the BCD digits into
6997 separate ASCII decimal digits. The major work involves scaling the
6998 floating-point value to the comparatively limited range of BCD values. To
6999 print a 9-digit result requires accurately scaling the given value to an
7000 integer between 10^(8) and 10^(9). For example, the number +0.123456789
7001 requires a scaling factor of 10^(9) to produce the value +123456789.0,
7002 which can be stored in 9 BCD digits. The scale factor must be an exact
7003 power of 10 to avoid to changing any of the printed digit values.
7005 These routines should exactly convert all values exactly representable in
7006 decimal in the field size given. Integer values that fit in the given string
7007 size will not be scaled, but directly stored into the BCD form. Noninteger
7008 values exactly representable in decimal within the string size limits will
7009 also be exactly converted. For example, 0.125 is exactly representable in
7010 binary or decimal. To convert this floating-point value to decimal, the
7011 scaling factor will be 1000, resulting in 125. When scaling a value, the
7012 function must keep track of where the decimal point lies in the final
7013 decimal value.
7016 Description of Operation
7017 Converting a floating-point number to decimal ASCII takes three major
7018 steps: identifying the magnitude of the number, scaling it for the BCD data
7019 type, and converting the BCD data type to a decimal ASCII string.
7021 Identifying the magnitude of the result requires finding the value X such
7022 that the number is represented by I*10^(X), where 1.0 <= I < 10.0. Scaling
7023 the number requires multiplying it by a scaling factor 10^(S), so that the
7024 result is an integer requiring no more decimal digits than provided for in
7025 the ASCII string.
7027 Once scaled, the numeric rounding modes and BCD conversion put the number
7028 in a form easy to convert to decimal ASCII by host software.
7030 Implementing each of these three steps requires attention to detail. To
7031 begin with, not all floating-point values have a numeric meaning. Values
7032 such as infinity, indefinite, or Not a Number (NaN) may be encountered by
7033 the conversion routine. The conversion routine should recognize these
7034 values and identify them uniquely.
7036 Special cases of numeric values also exist. Denormals, unnormals, and
7037 pseudo zero all have a numeric value but should be recognized, because all
7038 of them indicate that precision was lost during some earlier calculations.
7040 Once it has been determined that the number has a numeric value, and it is
7041 normalized setting appropriate unnormal flags, the value must be scaled to
7042 the BCD range.
7045 Scaling the Value
7046 To scale the number, its magnitude must be determined. It is sufficient to
7047 calculate the magnitude to an accuracy of 1 unit, or within a factor of 10
7048 of the given value. After scaling the number, a check will be made to see if
7049 the result falls in the range expected. If not, the result can be adjusted
7050 one decimal order of magnitude up or down. The adjustment test after the
7051 scaling is necessary due to inevitable inaccuracies in the scaling value.
7053 Because the magnitude estimate need only be close, a fast technique is
7054 used. The magnitude is estimated by multiplying the power of 2, the unbiased
7055 floating-point exponent, associated with the number by log{10}2. Rounding
7056 the result to an integer will produce an estimate of sufficient accuracy.
7057 Ignoring the fraction value can introduce a maximum error of 0.32 in the
7058 result.
7060 Using the magnitude of the value and size of the number string, the scaling
7061 factor can be calculated. Calculating the scaling factor is the most
7062 inaccurate operation of the conversion process. The relation
7063 10^(X)=2**(X * log{2}10) is used for this function. The exponentiate
7064 instruction (F2XM1) will be used.
7066 Due to restrictions on the range of values allowed by the F2XM1
7067 instruction, the power of 2 value will be split into integer and fraction
7068 components. The relation 2**(I + F) = 2**I * 2**F allows using the FSCALE
7069 instruction to recombine the 2**F value, calculated through F2XM1, and the
7070 2**I part.
7073 Inaccuracy in Scaling
7074 The inaccuracy of these operations arises because of the trailing zeros
7075 placed into the fraction value when stripping off the integer valued bits.
7076 For each integer valued bit in the power of 2 value separated from the
7077 fraction bits, one bit of precision is lost in the fraction field due to
7078 the zero fill occurring in the least significant bits.
7080 Up to 14 bits may be lost in the fraction because the largest allowed
7081 floating point exponent value is 2^(14) - 1.
7084 Avoiding Underflow and Overflow
7085 The fraction and exponent fields of the number are separated to avoid
7086 underflow and overflow in calculating the scaling values. For example, to
7087 scale 10^(4932) to 10^(8) requires a scaling factor of 10^(4950), which
7088 cannot be represented by the NPX.
7090 By separating the exponent and fraction, the scaling operation involves
7091 adding the exponents separate from multiplying the fractions. The exponent
7092 arithmetic will involve small integers, all easily represented by the NPX.
7095 Final Adjustments
7096 It is possible that the power function (Get_Power_10) could produce a
7097 scaling value such that it forms a scaled result larger than the ASCII field
7098 could allow. For example, scaling 9.9999999999999999 * 10^(4900) by
7099 1.00000000000000010 * 10^(-4883) would produce 1.00000000000000009 *
7100 10^(18). The scale factor is within the accuracy of the NPX and the result
7101 is within the conversion accuracy, but it cannot be represented in BCD
7102 format. This is why there is a post-scaling test on the magnitude of the
7103 result. The result can be multiplied or divided by 10, depending on whether
7104 the result was too small or too large, respectively.
7107 Output Format
7108 For maximum flexibility in output formats, the position of the decimal
7109 point is indicated by a binary integer called the power value. If the power
7110 value is zero, then the decimal point is assumed to be at the right of the
7111 rightmost digit. Power values greater than zero indicate how many trailing
7112 zeros are not shown. For each unit below zero, move the decimal point to the
7113 left in the string.
7115 The last step of the conversion is storing the result in BCD and indicating
7116 where the decimal point lies. The BCD string is then unpacked into ASCII
7117 decimal characters. The ASCII sign is set corresponding to the sign of the
7118 original value.
7121 Trigonometric Calculation Examples
7122 The 80287 instruction set does not provide a complete set of trigonometric
7123 functions that can be used directly in calculations. Rather, the basic
7124 building blocks for implementing trigonometric functions are provided by the
7125 FPTAN and FPREM instructions. The example in figure 4-7 shows how three
7126 trigonometric functions (sine, cosine, and tangent) can be implementing
7127 using the 80287. All three functions accept a valid angle argument between
7128 -2^(62) and +2^(62). These functions may be called from PL/M-286,
7129 Pascal-286, FORTRAN-286, or ASM286 routines.
7131 These trigonometric functions use the partial tangent instruction together
7132 with trigonometric identities to calculate the result. They are accurate to
7133 within 16 units of the low 4 bits of an extended precision value. The
7134 functions are coded for speed and small size, with tradeoffs available for
7135 greater accuracy.
7137 Figure 4-7. Calculating Trigonometric Functions
7140 iAPX286 MACRO ASSEMBLER   80287 Trigonometric functions           10:13:51 09/25/83 PAGE   1
7142 SERIES-888 iAPX286 MACRO ASSEMBLER X108 ASSEMBLY OF MODULE TRIG_FUNCTIONS
7143 OBJECT MODULE PLACED IN :F3:TRIG.OBJ
7144 ASSEMBLER INVOKED BY:  ASM286.86 :F3:TRIG.AP2
7146 LOC  OBJ           LINE     SOURCE
7148                       1  +1   $title("80287 Trigonometric Functions")
7149                       2
7150                       3                       name    trig_functions
7151                       4                       public  sine,cosine,tangent
7152                       5
7153 ----                  6       stack           stackseg        6           ; Reserve local space
7154                       7
7155    #                  8       sw_287          record  res1:1,cond3:1,top:3,cond2:1,cond1:1,cond0:1,
7156                       9                               res2:8
7157                      10
7158 ----                 11       code            segment er public
7159                      12       ;
7160                      13       ;         Define local constants
7161                      14       ;
7162                      15                       even
7163 0000 35C26821A2DA0F  16       pi_quarter      dt      3FFEC90FDAA22168C235R ; PI/4
7164      C9FE3F
7165 000A 0000C0FF        17       indefinite      dd      0FFC000000R         ; Indefinite special value
7166                      18  +1   $eject
7167                      19       ;
7168                      20       ;         This subroutine calculates the sine or cosine of the angle, given in
7169                      21       ;       radians.  The angle is in ST(0), the returned value will be in ST(0).
7170                      22       ;       The result is accurate to within 7 units of the least significant three
7171                      23       ;       bits of the NPX extended real format.  The PLM/86 definition is:
7172                      24       ;
7173                      25       ;       sine:   procedure (angle) real external,
7174                      26       ;               declare angle real;
7175                      27       ;               and sine;
7176                      28       ;
7177                      29       ;       cosine: procedure (angle) real external;
7178                      30       ;               declare angle real;
7179                      31       ;               and cosine;
7180                      32       ;
7181                      33       ;         Three stack registers are required.  The result of the function
7182                      34       ;       defined as follows for the following arguments:
7183                      35       ;
7184                      36       ;                       angle                                   result
7185                      37       ;
7186                      38       ;               valid or unnormal less than 2**62 in magnitude  correct value
7187                      39       ;               zero                                            0 or 1
7188                      40       ;               denormal                                        correct denormal
7189                      41       ;               valid or unnormal greater than 2**62            indefinite
7190                      42       ;               infinity                                        indefinite
7191                      43       ;               NAN                                             NAN
7192                      44       ;               empty                                           empty
7193                      45 +1    $eject
7194                      46       ;
7195                      47       ;         This function is based on the NPX fptan instruction.  The fptan
7196                      48       ;       instruction will only work with an angle of from 0 to PI/4.  With this
7197                      49       ;       instruction, the sine or cisone of angles from 0 to PI/4 can be accurately
7198                      50       ;       calculated.  The technique used by this routine can calculate a general
7199                      51       ;       sine or cosine by using one of four possible operations:
7200                      52       ;
7201                      53       ;                   Let R = |angle mod PI/4|
7202                      54       ;                       S = -1 or 1, according to the sign of the angle
7203                      55       ;
7204                      56       ;       1) sin(R)   2) cos(R)   3) sin(PI/4-R)  4) cos(PI/4-R)
7205                      57       ;
7206                      58       ;         The choice of the relation and the sign of the result follows
7207                      59       ;       decision table shown below based on the octant the angle falls in:
7208                      60       ;
7209                      61       ;               octant          sine            cosine
7210                      62       ;
7211                      63       ;                 0              s*1               2
7212                      64       ;                 1              s*4               3
7213                      65       ;                 2              s*2            -1*1
7214                      66       ;                 3              s*3            -1*4
7215                      67       ;                 4             -s*1            -1*2
7216                      68       ;                 5             -s*4            -1*3
7217                      69       ;                 6             -s*2               1
7218                      70       ;                 7             -s*3               4
7219                      71       ;
7220                      72 +1    $eject
7221                      73       ;
7222                      74       ;         Angle to sine function is a zero or unnormal
7223                      75       ;
7224 000E                 76       sine_zero_unnormal:
7225                      77
7226 000E DDD9            78               fstp    st(1)                           ; Remove PI/4
7227 0010 7501            79               jnz     enter_sine_normalize            ; Jump if angle is unnormal
7228                      80       ;
7229                      81       ;         Angle is a zero.
7230                      82       ;
7231 0012 C3              83               ret
7232                      84       ;
7233                      85       ;         Angle is an unnormal
7234                      86       ;
7235 0013                 87       enter_sine_normalize:
7236                      88
7237 0013 E80901          89               call    normalize_value
7238 0016 EB2F            90               jmp     short enter_sine
7239                      91
7240 0018                 92       cosine  proc                                    ; Entry point to cosine
7241                      93
7242 0018 D9E5            94               fxam                                    ; Look at the value
7243 00A1 9BDF30          95               fstsw   ax                              ; Store status value
7244 001D 2EDB2E0000   R  96               fld     pi_quarter                      ; Setup for angle reduce
7245 0022 B101            97               mov     c1,1                            ; Signal cosine function
7246 0024 9E              98               sahf                                    ; ZF = C3, PF = C2, CF = C0
7247 0025 7263            99               jc      funny_parameter                 ; Jump if parameter is
7248                     100                                                       ; empty, NAN, or infinity
7249                     101       ;
7250                     102       ;         Angle is unnormal, normal, zero, denormal.
7251                     103       ;
7252 0027 D9C9           104               fxch                                    ; st(0) = angle, st(1) = PI/4
7253 0029 7A1C           105               jpe     enter_sine                      ; Jump if normal or denormal
7254                     106       ;
7255                     107       ;         Angle is an unnormal or zero
7256                     108       ;
7257 002B DDD9           109               fstp    st(1)                           ; Remove PI/4
7258 002D 75E4           110               jnz     enter_sine_normalize
7259                     111       ;
7260                     112       ;         Angle is a zero, cos(0) = 1.0
7261                     113       ;
7262 002F DDD8           114               fstp    st(0)                       ; Remove 0
7263 0031 D9E8           115               fldl                                ; Return 1
7264 0033 C3             116               ret
7265                     117       ;
7266                     118       ;         All work is done as a sine function.  By adding PI/2 to the angle
7267                     119       ;       a cosine is converted to a sine.  Of course the angle addition is not
7268                     120       ;       done to the argument but rather to the program logic control values.
7269                     121       ;
7270 0034                122       sine                                        ; Entry point for sine function
7271                     123
7272 0034 D9E5           124               fxam                                ; Look at the parameter
7273 0036 9BDFE0         125               fstsw   ax                          ; Look at fxam status
7274 0039 2EDB2E0000   R 126               fld     pi_quarter                  ; Get PI/4 value
7275 003E 9E             127               sahf                                ; CF = C0, PF = C2, ZF - C3
7276 003F 7249           128               jc      funny_parameter             ; Jump if empty, NAN, or infinity
7277                     129       ;
7278                     130       ;         Angle is unnormal, normal, zero, or denormal
7279                     131       ;
7280 0041 D9C9           132               fxch                                ; ST(1) = PI/4, st(0) angle
7281 0043 B100           133               mov     c1,0                        ; Signal sine
7282 0045 7BC7           134               jpo     sine_zero_unnormal          ; Jump if zero or unnormal
7283                     135       ;
7284                     136       ;         ST(0) is either a normal or denormal value.  Both will work
7285                     137       ;       Use the fprem instruction to accurately reduce the range of the given
7286                     138       ;       angle to within 0 and PI/4 in magnitude.  If fprem cannot reduce the
7287                     139       ;       angle in one shot, the angle is too big to be meaningful, >2**62
7288                     140       ;       radians.  Any roundoff error in the calculation of the angle given
7289                     141       ;       could completely change the result of this function.  It is safest to
7290                     142       ;       call this very rare case an error.
7291                     143       ;
7292 0047                144       enter_sine
7293 0047 D9F8           145               fprem                               ; Reduce angle
7294                     146                                                   ; Note that fprem will force a
7295                     147                                                   ; denormal to a very small unnormal
7296                     148                                                   ; Fptan of a very small unnormal
7297                     149                                                   ; will be the same very small
7298                     150                                                   ; unnormal, which is correct.
7299 0049 93             151               xchg    ax,bx                       ; Save old status in BX
7300 004A 9BDFE0         152               fstsw   ax                          ; Check if reduction was complete
7301                     153                                                   ; Quotient in C0,C3,C1
7302 004D 93             154               xchg    ax,bx                       ; Put new status in bx
7303 004E F6C704         155               test    bh,high(mask cond2)         ; sin(2*N*PI+x) = sin(x)
7304 0051 7544           156               jnz     angle_too_big
7305                     157       ;
7306                     158       ;         Set sign flags and test for which eighth of the revolution the
7307                     159       ;       angle fell intl.
7308                     160       ;
7309                     161       ;       Assert -PI/4 < st(0) < PI/4
7310                     162       ;
7311 0053 D9E1           163               fabs                                ; Force the argument positive
7312                     164                                                   ; cond1 bit in bx holds the sign.
7313 0055 0AC9           165               or      c1,c1                       ; Test for sine or cosine function
7314 0057 740F           166               jz      sine_select                 ; Jump if sine function
7315                     167       ;
7316                     168       ;         This is a cosine function.  Ignore the original sign of the angle
7317                     169       ;       and add a quarter revolution to the octant id from the fprem instruction
7318                     170       ;       cos(A) = sin(A+PI/2) and cos(|A|) = cos(A)
7319                     171       ;
7320 0059 B0E4FD         172               and     ah,not high(mask cond1)     ; Turn off sign of argument
7321 005C B0CF80         173               or      by,80H                      ; Prepare to add 010 to c0,c3,c1
7322                     174                                                   ; status value in ax
7323                     175                                                   ; Set busy bit so carry out from
7324 005F 80C740         176               add     bh,high(mask cond3)         ; C3 will go into the carry flag
7325 0062 B000           177               mov     al,0                        ; Extract carry flag
7326 0064 D0D0           178               rcl     al,1                        ; Put carry flag in low bit
7327 0066 32FB           179               xor     bh,al                       ; Add carry to C0 not changing
7328                     180                                                   ; C1 flag
7329                     181       ;
7330                     182       ;         See if the argument should be reversed, depending on the octant in
7331                     183       ;       which the argument fell during fprem.
7332                     184       ;
7333 0068                185       sine_select:
7334                     186
7335 0068 F6C702         187               test    bh,high(mask cond1)         ; Reverse angle if C1 = 1
7336 006B 7404           188               jz      no_sine_reverse
7337                     189       ;
7338                     190       ;         Angle was in octants 1,3,5,7.
7339                     191       ;
7340 006D DEE9           192               fsub                                ; Invert sense of rotation
7341 006F EB0E           193               jmp     short do_sine_fptan         ; 0 < arg <= PI/4
7342                     194       ;
7343                     195       ;         Angle was in octants 0,2,4,6
7344                     196       ;       Test for a zero argument since fptan will not work if st(0) = 0
7345                     197       ;
7346 0071                198       no_sine_reverse:
7347                     199
7348 0071 D9E4           200               ftst                                ; Test for zero angle
7349 0073 91             201               xchg    ax,cx
7350 0074 9BDFE0         202               fstsw   ax                          ; cond3 = 1 if st(0) = 0
7351 0077 91             203               xchg    ax,cx
7352 0078 DDD9           204               fstp    st(1)                       ; Remove PI/4
7353 007A F6C540         205               test    ch,high(mask cond3)         ; If c3=1, argument is zero
7354 007D 7514           206               jnz     sine_argument_zero
7355                     207       ;
7356                     208       ;       Assert: 0 < st(0) <= PI/4
7357                     209       ;
7358 007F                210       do_sine_fptan:
7359                     211
7360 007F D9F2           212               fptan                                   ; TAN ST(0) = ST(1)/ST(0) = Y/X
7361                     213
7362 0081                214       after_sine_fptan:
7363                     215
7364 0081 F6C742         216               test    bh,high(mask cond3 + mask cond1); Look at octant angle fell into
7365 0084 7B1A           217               jpo     x_numerator                     ; Calculate cosine for octants
7366                     218                                                       ; 1,2,5,6
7367                     219       ;
7368                     220       ;         Calculate the sine of the argument
7369                     221       ;       sine(A) = tan(A)/sqrt(1+tan(A)**2)      if tan(A) = Y/X then
7370                     222       ;       sin(A) = Y/sqrt(X*X + Y*Y)
7371                     223       ;
7372 0086 D9C1           224               fld     st(1)                           ; Copy Y value
7373 0088 EB1A           225               jmp     short finish_sine               ; Put Y value in numerator
7374                     226       ;
7375                     227       ;         The top of the stack is either NAN, infinity, or empty
7376                     228       ;
7377 008A                229       funny_parameter:
7378                     230
7379 008A DDD8           231               fstp    st(0)                           ; Remove PI/4
7380 008C 7404           232               jz      return_empty                    ; Return empty if no parm
7381                     233
7382 008E 7B02           234               jpo     return_NAN                      ; Jump if st(0) is NAN
7383                     235       ;
7384                     236       ;         st(0) is infinity.  Return an indefinite value.
7385                     237       ;
7386 0090 D9F8           238               fprem                                   ; ST(1) can be anything
7387                     239
7388 0092                240       return_NAN:
7389 0092                241       return_empty:
7390                     242
7391 0092 C3             243               ret                                     ; OK to leave fprem running
7392                     244       ;
7393                     245       ;       Simulate fptan with st(0) = 0
7394                     246       ;
7395 0093                247       sine_argument_zero:
7396                     248
7397 0093 D9EB           249               fld1                                    ; Simulate tan(0)
7398 0095 EBEA           250               jmp     after_sine_fptan                ; Return the zero value
7399                     251       ;
7400                     252       ;         The angle was too large.  Remove the modulus and dividend from the
7401                     253       ;       stack and return an indefinite result.
7402                     254       ;
7403 0097                255       angle_too_big:
7404                     256
7405 0097 DED9           257               fcompp                                  ; Pop two values from the stack
7406 0099 2ED9060A00   R 258               fld     indefinite                      ; Return indefinite
7407 009E 9B             259               fwait                                   ; Wait for load to finish
7408 009F C3             260               ret
7409                     261       ;
7410                     262       ;         Calculate the cosine of the argument
7411                     263       ;       cos(A) = 1/sqrt(1+tan(A)**2)    if tan(A) - Y/X then
7412                     264       ;       cos(A) = X/sqrt(X*X + Y*Y)
7413                     265       ;
7414 00A0                266       X_numerator:
7415                     267
7416 00A0 D9C0           268               fld     st(0)                           ; Copy X value
7417 00A2 D9CA           269               fxch    st(2)                           ; Put X in numerator
7418                     270
7419 00A4                271       finish_sine:
7420                     272
7421 00A4 DCCB           273               fmul    st,st(0)                        ; Form X*X + Y*Y
7423 00A6 D9C9           274               fxch
7424 00AB DCC8           275               fmul    st,st(0)
7425 00AA DEC1           276               fadd                                    ; st(0) = X*X + Y*Y
7426 00AC D9FA           277               fsqrt                                   ; st(0) = sqrt(X*X + Y*Y)
7427                     278
7428                     279
7429                     280       ;         Form the sign of th result.  The two conditions are the C1 flag from
7430                     281       ;       FXAM in bh and the CO flag from fprem in ah
7431                     282       ;
7432 00AE 80E701         283               and     bh,high(mask cond0)             ; Look at the fprem C0 flag
7433 00B1 80E402         284               and     ah,high(mask cond1)             ; Look at the fxam C1 flag
7434 00B4 0AFC           285               or      bh,ah                           ; Even number of flags cancel
7435 00B6 7A02           286               jpe     positive_sine                   ; Two negatives make a positive
7436                     287
7437 00B8 D9E0           288               fchs                                    ; Forc result negative
7438                     289
7439 00BA                290       positive_sine:
7440                     291
7441 00BA DEF9           292               fdiv                                    ; Form final result
7442 00BC C3             293               ret                                     ; Ok to leave fdiv running
7443                     294
7444                     295       cosine endp
7445                     296   +1  $eject
7446                     297       ;
7447                     298       ;         This function will calculate the tangent of an angle.
7448                     299       ;       The angle, in radians is passed in ST(0), the tangent is returned
7449                     300       ;       in ST(0).  The tangent is calculated to an accuracy of 4 units in the
7450                     301       ;       least three significant bits of an extended real format number.  The
7451                     302       ;       PLM/86 calling format is:
7452                     303       ;
7453                     304       ;     tangent   procedure (angle) real external;
7454                     305       ;               declare angle real;
7455                     306       ;               end tangent;
7456                     307       ;
7457                     308       ;         Two stack registers are used.  The result of the tangent function is
7458                     309       ;       defined for the following cases:
7459                     310       ;
7460                     311       ;                               angle                           result
7461                     312       ;
7462                     313       ;               valid or unnormal < 2**62 in magnitude          correct value
7463                     314       ;               0                                               0
7464                     315       ;               denormal                                        correct denormal
7465                     316       ;               valid or unnormal > 2**62 in magnitude          indefinite
7466                     317       ;               NAN                                             NAN
7467                     318       ;               infinity                                        indefinite
7468                     319       ;               empty                                           empty
7469                     320       ;
7470                     321       ;         The tangent instruction uses the fptan instruction.  Four possible
7471                     322       ;       relations are used:
7472                     323       ;
7473                     324       ;         Let R = |angle MOD PI/4|
7474                     325       ;             S = -1 or 1 depending on the sign of the angle
7475                     326       ;
7476                     327       ;       1) tan(R)   2) tan(PI/4-R)  3) 1/tan(R)     4) 1/tan(PI/4-R)
7477                     328       ;
7478                     329       ;         The following table is used to decide which relation to use depending
7479                     330       ;       on in which octant the angle fell.
7480                     331       ;
7481                     332       ;       octant          relation
7482                     333       ;
7483                     334       ;         0              s*1
7484                     335       ;         1              s*4
7485                     336       ;         2             -s*3
7486                     337       ;         3             -s*2
7487                     338       ;         4              s*1
7488                     339       ;         5              s*4
7489                     340       ;         6             -s*3
7490                     341       ;         7             -s*2
7491                     342       ;
7492 00BD                343       tangent proc
7493                     344
7494 00BD D9E5           345               fram                                    ; Look at the parameter
7495 00BF 9BDFE0         346               fstw    ax                              ; Get fxam status
7496 00C2 2EDB2E0000  R  347               fld     pi_quarter                      ; Get PI/4
7497 00C7 9E             348               sahf                                    ; CF = C1, PF = C2, ZF = C3
7498 00C8 72C0           349               jc      funny_parameter
7499                     350       ;
7500                     351       ;         Angle is unnormal, normal, zero, or denormal.
7501                     352       ;
7502 00CA D9C9           353               fxch                                    ; st(0) = angle, st(1) = PI/4
7503 00CC 7A17           354               jpe     tan_zero_unnormal
7504                     355       ;
7505                     356       ;         Angle is either an normal or denormal.
7506                     357       ;       Reduc the angle to the range -PI/4 < result < PI/4
7507                     358       ;       If fprem cannot perform this operation in one try, the magnitude of the
7508                     359       ;       angle must be > 2**62.  Such an angle is so large that any rounding
7509                     360       ;       errors could make a very large difference in the reduced angle.
7510                     361       ;       It is safest to call this very rare case an error.
7511                     362       ;
7512 00CE                363       tan_normal
7513                     364
7514 00CE D9F8           365               fprem                                   ; Quotient in C0,C3,C1
7515                     366                                                       ; Convert denormals into unnormals
7516 00D0 93             367               xchg    ax,bx
7517 00D1 9BDFE0         368               fstsw   ax                              ; Quotient identifies octant
7518                     369                                                       ; original angle fell into
7519 00D4 93             370               xchg    ax,bx
7520 00D5 F6C704         371               test    bh,high(mask cond2)             ; Test for complete reduction
7521 00D8 7BD            372               jnz     angle_too_big                   ; Exit if angle was too big
7522                     373       ;
7523                     374       ;         See if the angle must be reversed.
7524                     375       ;
7525                     376       ;       Assert -PI/4 < st(0) < PI/4
7526                     377       ;
7527 00DA D9E1           378               fabs                                    ; 0 <= st(0) < PI/4
7528                     379                                                       ; C3 in bx has the sign flag
7529 00DC F6C702         380               test    bh,high(mask cond1)             ; must be reversed
7530 00DF 740E           381               jz      no_tan_reverse
7531                     382       ;
7532                     383       ;         Angle fell in octants 1,3,5,7.  Reverse it, subtract it from PI/4.
7533                     384       ;
7534 00E1 DEE9           385               fsub                                    ; Reverse angle
7535 00E3 EB18           386               jmp     short do_tangent
7536                     387       ;
7537                     388       ;         Angle is either zero or an unnormal
7538                     389       ;
7539 00E5                390       tan_zero_unnormal:
7540                     391
7541 00E5 DDD9           392               fstp    st(1)                           ; Remove PI/4
7542 00E7 7405           393               jz      tan_angle_zero
7543                     394       ;
7544                     395       ;       Angle is an unnormal.
7545                     396       ;
7546 00E9 E83300         397               call    normalize_value
7547 00EC EBE0           398               jmp     tan_normal
7548                     399
7549 00EE                400       tan_angle_zero:
7550                     401
7551 00EE C3             402               ret
7552                     403       ;
7553                     404                 Angle fell in octants 0,2,4,6. Test for st(0) = 0, fptan won't work
7554                     405       ;
7555 00EF                406       no_tan_reverse:
7556                     407
7557 00EF D9E4           408               ftst                                    ; Test for zero angle
7558 00F1 91             409               xchg    ax,cx
7559 00F2 9BDFE0         410               fstsw   ax                              ; C3 = 1 if st(0) = 0
7560 00F5 91             411               fstp    st(1)
7561 00F6 DDD9           412               test    ch,high(mask cond3)
7562 00F8 F6C540         413               jnz     tan_zero
7563 00FB 7515           414
7564                     415       do_tangent:
7565 00FD                416
7566                     417               fptan                                   ; tan ST(0) = ST(0)/ST(0)
7567 00FD D9F2           418
7568                     419       after_tangent:
7569 00FF                420       ;
7570                     421       ;         Decide on the order of the operands and their sign for the divide
7571                     422       ;       operation while the fptan instruction is working.
7572                     423       ;
7573                     424               mov     al,bh                           ; Get a copy of fprem C3 flag
7574 00FF 8AC7           425               and     ax,mask cond1 + high(mask cond3); Examine fprem C3 flag and
7575 0101 254002         426                                                       ; FXAM C1 flag
7576                     427               test    bh,high(mask cond1 + mask cond3); Use reverse divide if in
7577 0104 F6C742         428                                                       ; octants 1,2,5,6
7578                     429               jpo     reverse_divide                  ; Note: parity works on low
7579 0107 7B0D           430                                                       ;  8 bits only!
7580                     431       ;
7581                     432       ;         Angle was in octants 0,3,4,7
7582                     433       ;       Test for the sign of the result.  Two negatives cancel.
7583                     434       ;
7584                     435               or      al,ah
7585 0109 0AC4           436               jpe     positive_divide
7586 010B 7A02           437
7587                     438               fchs                                    ; Force result negative
7588 010D D9E0           439
7589                     440       positive_divide:
7590 010F                441
7591                     442               fdiv                                    ; Form result
7592 010F DEF9           443               ret                                     ; Ok to leave fdiv running
7593 0111 C3             444
7594                     445       tan_zero:
7595 0112                446
7596                     447               fld1                                    ; Force 1/0 = tan(PI/2)
7597 0112 D9E8           448       ;
7598 0114 EBE9           449       ;         Angle was in octants 1,2,5,6
7599                     450       ;       Set the correct sign of the result
7600                     451       ;
7601                     452       reverse_divide:
7602                     453
7603 0116                454               or      al,ah
7604                     455               jpe     positive_r_divide
7605 0116 0AC4           456
7606 0118 7A02           457               fchs                                    ; Force result negative
7607                     458
7608 011A D9E0           459       positive_r_divide:
7609                     460
7610 011C                461               fdivr                                   ; Form reciprocal of result
7611                     462               ret                                     ; Ok to leave fdiv running
7612 011C DEF1           463
7613 011E C3F1           464       tangent endp
7614                     465       ;
7615                     466       ;         This function will normalize the value in st(0)
7616                     467       ;       Then PI/4 is placed into st(1).
7617                     468       ;
7618                     469       normalize_value:
7619                     470
7620 011F                471               fabs                                    ; Force value positive
7621                     472               fxtract                                 ; 0 <= st(0) < 1
7622 011F D9E1           473               fld1                                    ; Get normalize bit
7623 0121 D9F4           474               fadd    st(1),st                        ; Normalize fraction
7624 0123 D9E8           475               fsub                                    ; Resotre original value
7625 0125 DCC1           476               fscale                                  ; Form original normalized value
7626 0127 DEE9           477               fstp    st(1)                           ; Remove scale factor
7627 0129 D9FD           478               fld     pi_quarter                      ; Get PI/4
7628 012B DDD9           479               fxch
7629 012D 2EDB2E0000  R  480               ret
7630 0132 D9C9           481
7631 0134 C3             482       code    ends
7632                     483
7633 ----                484
7634                     485
7636 ASSEMBLY COMPLETE,            NO WARNINGS,   NO ERRORS
7639 FPTAN and FPREM
7640 These trigonometric functions use the FPTAN instruction of the NPX. FPTAN
7641 requires that the angle argument be between 0 and Ò/4 radians, 0 to 45
7642 degrees. The FPREM instruction is used to reduce the argument down to this
7643 range. The low three quotient bits set by FPREM identify which octant the
7644 original angle was in.
7646 One FPREM instruction iteration can reduce angles of 10^(18) radians or less
7647 in magnitude to Ò/4! Larger values can be reduced, but the meaning of the
7648 result is questionable, because any errors in the least significant bits of
7649 that value represent changes of 45 degrees or more in the reduced angle.
7652 Cosine Uses Sine Code
7653 To save code space, the cosine function uses most of the sine function
7654 code. The relation sin (�A� + Ò/2) = cos(A) is used to convert the
7655 cosine argument into a sine argument. Adding Ò/2 to the angle is performed
7656 by adding 010{2} to the FPREM quotient bits identifying the argument's
7657 octant.
7659 It would be very inaccurate to add Ò/2 to the cosine argument if it was
7660 very much differentfrom Ò/2.
7662 Depending on which octant the argument falls in, a different relation will
7663 be used in the sine and tangent functions. The program listings show which
7664 relations are used.
7666 For the tangent function, the ratio produced by FPTAN will be directly
7667 evaluated. The sine function will use either a sine or cosine relation
7668 depending on which octant the angle fell into. On exit, these functions will
7669 normally leave a divide instruction in progress to maintain concurrency.
7671 If the input angles are of a restricted range, such as from 0 to 45
7672 degrees, then considerable optimization is possible since full angle
7673 reduction and octant identification is not necessary.
7675 All three functions begin by looking at the value given to them. Not a
7676 Number (NaN), infinity, or empty registers must be specially treated.
7677 Unnormals need to be converted to normal values before the FPTAN instruction
7678 will work correctly. Denormals will be converted to very small unnormals
7679 that do work correctly for the FPTAN instruction. The sign of the angle is
7680 saved to control the sign of the result.
7682 Within the functions, close attention was paid to maintain concurrent
7683 execution of the 80287 and host. The concurrent execution will effectively
7684 hide the execution time of the decision logic used in the program.
7687 Appendix A  Machine Instruction Encoding and Decoding
7689 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7691 Machine instructions for the 80287 come in one of five different forms as
7692 shown in table A-1. In all cases, the instructions are at least two bytes
7693 long and begin with the bit pattern 11011B, which identifies the ESCAPE
7694 class of instructions. Instructions that reference memory operands are
7695 encoded much like similar CPU instructions, because all of the CPU
7696 memory-addressing modes may be used with ESCAPE instructions.
7698 Note that several of the processor control instructions (see table 2-11 in
7699 Chapter Two) may be preceded by an assembler-generated CPU WAIT instruction
7700 (encoding: 10011011B) if they are programmed using the WAIT form of their
7701 mnemonics. The ASM286 assembler inserts a WAIT instruction only before these
7702 specific processor control instructions‘‘all of the numeric instructions are
7703 automatically synchronized by the 80286 CPU and an explicit WAIT
7704 instruction, though allowed, is not necessary.
7706 Table A-2 lists all 80287 machine instructions in binary sequence. This
7707 table may be used to "disassemble" instructions in unformatted memory dumps
7708 or instructions monitored from the data bus. Users writing exception
7709 handlers may also find this information useful to identify the offending
7710 instruction.
7713 Table A-1. 80287 Instruction Encoding
7715   ’‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘“
7716   � Lower-Addressed Byte  �     Higher-Addressed Byte   �  0, 1, or 2 bytes �
7717   –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘˜‘‘‘‘‘‘‘š‘‘‘˜‘‘‘‘‘‘‘˜‘‘‘˜‘‘‘‘‘˜‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
7719 Memory transfers, including applicable processor control instructions;
7720 0, 1, or 2 displacement bytes may follow.� 1  1  0  1  1 � OP-A  � 1 �  MOD  � 1 �OP-B �  R/M  �   DISPLACEMENT    �
7721   –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘š‘‘‘š‘‘‘‘‘‘‘š‘‘‘™‘‘‘‘‘š‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘—
7723 Memory arithmetic and comparison instructions; 0, 1, or 2 displacement
7724 bytes may follow.� 1  1  0  1  1 �FORMAT �OP-A  MOD  �  OP-B   �  R/M  �   DISPLACEMENT    �
7725   –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘˜‘‘‘š‘‘‘š‘‘‘˜‘‘‘š‘‘‘‘‘‘‘‘‘š‘‘‘‘‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘•
7727 Stack arithmetic and comparison instructions.� 1  1  0  1  1 � R � P �OP-A 1 � 1 �  OP-B   �  REG  �
7728   –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘˜‘‘‘‘‘™‘‘‘‘‘‘‘—
7730 Constant, transcendental, some arithmetic instructions.� 1  1  0  1  1 � 0 � 0 � 1 � 1 � 1 � 1 �     OP      �
7731   –‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘š‘‘‘‘‘‘‘‘‘‘‘‘‘—
7733 Processor control instructions that do not reference memory.� 1  1  0  1  1 � 0 � 1 � 1 � 1 � 1 � 1 �     OP      �
7734   ”‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘™‘‘‘‘‘‘‘‘‘‘‘‘‘•
7735     7  6  5  4  3   2   1   0   7   6   5   4  3  2  1  0
7737 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7738 NOTES
7740   OP, OP-A, OP-B: Instruction opcode, possibly split into two fields.
7742   MOD: Same as 80286 CPU mode field.
7744   R/M: Same as 80286 CPU register/memory field.
7746   FORMAT: Defines memory operand
7747     00 = short real
7748     01 = short integer
7749     10 = long real
7750     11 = word integer
7752   R: 0 = return result to stack top
7753      1 = return result to other register
7755   P: 0 = do not pop stack
7756      1 = pop stack after operation
7758   REG: register stack element
7759    000 = stack top
7760    001 = next on stack
7761    010 = third stack element, etc.
7762 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7765 Table A-2. Machine Instruction Decoding Guide
7768 ’‘1st  Byte‘‘“                                        ASM286 Instruction
7769 Hex     Binary     2nd Byte        Bytes 3, 4               Format
7771 D8   1101  1000   MOD00  0R/M  (disp-lo),(disp-hi)    FADD     short-real
7772 D8   1101  1000   MOD00  1R/M  (disp-lo),(disp-hi)    FMUL     short-real
7773 D8   1101  1000   MOD01  0R/M  (disp-lo),(disp-hi)    FCOM     short-real
7774 D8   1101  1000   MOD01  1R/M  (disp-lo),(disp-hi)    FCOMP    short-real
7775 D8   1101  1000   MOD10  0R/M  (disp-lo),(disp-hi)    FSUB     short-real
7776 D8   1101  1000   MOD10  1R/M  (disp-lo),(disp-hi)    FSUBR    short-real
7777 D8   1101  1000   MOD11  0R/M  (disp-lo),(disp-hi)    FDIV     short-real
7778 D8   1101  1000   MOD11  1R/M  (disp-lo),(disp-hi)    FDIVR    short-real
7779 D8   1101  1000   1100   0REG                         FADD     ST,ST(i)
7780 D8   1101  1000   1100   1REG                         FMUL     ST,ST(i)
7781 D8   1101  1000   1101   0REG                         FCOM     ST(i)
7782 D8   1101  1000   1101   1REG                         FCOMP    ST(i)
7783 D8   1101  1000   1110   0REG                         FSUB     ST,ST(i)
7784 D8   1101  1000   1110   1REG                         FSUBR    ST,ST(i)
7785 D8   1101  1000   1111   0REG                         FDIV     ST,ST(i)
7786 D8   1101  1000   1111   1REG                         FDIVR    ST,ST(i)
7787 D9   1101  1001   MOD00  0R/M  (disp-lo),(disp-hi)    FLD      short-real
7788 D9   1101  1001   MOD00  1R/M                         reserved
7789 D9   1101  1001   MOD01  0R/M  (disp-lo),(disp-hi)    FST      short-real
7790 D9   1101  1001   MOD01  1R/M  (disp-lo),(disp-hi)    FSTP     short-real
7791 D9   1101  1001   MOD10  0R/M  (disp-lo),(disp-hi)    FLDENV   14-bytes
7792 D9   1101  1001   MOD10  1R/M  (disp-lo),(disp-hi)    FLDCW    2-bytes
7793 D9   1101  1001   MOD11  0R/M  (disp-lo),(disp-hi)    FSTENV   14-bytes
7794 D9   1101  1001   MOD11  1R/M  (disp-lo),(disp-hi)    FSTCW    2-bytes
7795 D9   1101  1001   1100   0REG                         FLD      ST(i)
7796 D9   1101  1001   1100   1REG                         FXCH     ST(i)
7797 D9   1101  1001   1101   0000                         FNOP
7798 D9   1101  1001   1101   0001                         reserved
7799 D9   1101  1001   1101   001-                         reserved
7800 D9   1101  1001   1101   01--                         reserved
7801 D9   1101  1001   1101   1REG                         (1)
7802 The marked encodings are not generated by the language translators. If,
7803 however, the 80287 encounters one of these encodings in the instruction
7804 stream, it will execute it as follows: FSTP ST(i)
7808 D9   1101  1001   1110   0000                         FCHS
7809 D9   1101  1001   1110   0001                         FABS
7810 D9   1101  1001   1110   001-                         reserved
7811 D9   1101  1001   1110   0100                         FTST
7812 D9   1101  1001   1110   0101                         FXAM
7813 D9   1101  1001   1110   011-                         reserved
7814 D9   1101  1001   1110   1000                         FLD1
7815 D9   1101  1001   1110   1001                         FLDL2T
7816 D9   1101  1001   1110   1010                         FLDL2E
7817 D9   1101  1001   1110   1011                         FLDPI
7818 D9   1101  1001   1110   1100                         FLDLG2
7819 D9   1101  1001   1110   1101                         FLDLN2
7820 D9   1101  1001   1110   1110                         FLDZ
7821 D9   1101  1001   1110   1111                         reserved
7822 D9   1101  1001   1111   0000                         F2XM1
7823 D9   1101  1001   1111   0001                         FYL2X
7824 D9   1101  1001   1111   0010                         FPTAN
7825 D9   1101  1001   1111   0011                         FPATAN
7826 D9   1101  1001   1111   0100                         FXTRACT
7827 D9   1101  1001   1111   0101                         reserved
7828 D9   1101  1001   1111   0110                         FDECSTP
7829 D9   1101  1001   1111   0111                         FINCSTP
7830 D9   1101  1001   1111   1000                         FPREM
7831 D9   1101  1001   1111   1001                         FYL2XP1
7832 D9   1101  1001   1111   1010                         FSQRT
7833 D9   1101  1001   1111   1011                         reserved
7834 D9   1101  1001   1111   1100                         FRNDINT
7835 D9   1101  1001   1111   1101                         FSCALE
7836 D9   1101  1001   1111   111-                         reserved
7837 DA   1101  1010   MOD00  0R/M  (disp-lo),(disp-hi)    FIADD    short-integer
7838 DA   1101  1010   MOD00  1R/M  (disp-lo),(disp-hi)    FIMUL    short-integer
7839 DA   1101  1010   MOD01  0R/M  (disp-lo),(disp-hi)    FICOM    short-integer
7840 DA   1101  1010   MOD01  1R/M  (disp-lo),(disp-hi)    FICOMP   short-integer
7841 DA   1101  1010   MOD10  0R/M  (disp-lo),(disp-hi)    FISUB    short-integer
7842 DA   1101  1010   MOD10  1R/M  (disp-lo),(disp-hi)    FISUBR   short-integer
7843 DA   1101  1010   MOD11  0R/M  (disp-lo),(disp-hi)    FIDIV    short-integer
7844 DA   1101  1010   MOD11  1R/M  (disp-lo),(disp-hi)    FIDIVR   short-integer
7845 DA   1101  1010   11--  ----                          reserved
7846 DB   1101  1011   MOD00  0R/M  (disp-lo),(disp-hi)    FILD     short-integer
7847 DB   1101  1011   MOD00  1R/M  (disp-lo),(disp-hi)    reserved
7848 DB   1101  1011   MOD01  0R/M  (disp-lo),(disp-hi)    FIST     short-integer
7849 DB   1101  1011   MOD01  1R/M  (disp-lo),(disp-hi)    FISTP    short-integer
7850 DB   1101  1011   MOD10  0R/M  (disp-lo),(disp-hi)    reserved
7851 DB   1101  1011   MOD10  1R/M  (disp-lo),(disp-hi)    FLD      temp-real
7852 DB   1101  1011   MOD11  0R/M  (disp-lo),(disp-hi)    reserved
7853 DB   1101  1011   MOD11  1R/M  (disp-lo),(disp-hi)    FSTP     temp-real
7854 DB   1101  1011   110-   ----                         reserved
7855 DB   1101  1011   1110   0000                         reserved (8087 FENI)
7856 DB   1101  1011   1110   0001                         reserved (8087 FDISI)
7857 DB   1101  1011   1110   0010                         FCLEX
7858 DB   1101  1011   1110   0011                         FINIT
7859 DB   1101  1011   1110   0100                         FSETPM
7860 DB   1101  1011   1110   1---                         reserved
7861 DB   1101  1011   1111   ----                         reserved
7862 DC   1101  1100   MOD00  0R/M  (disp-lo),(disp-hi)    FADD     long-real
7863 DC   1101  1100   MOD00  1R/M  (disp-lo),(disp-hi)    FMUL     long-real
7864 DC   1101  1100   MOD01  0R/M  (disp-lo),(disp-hi)    FCOM     long-real
7865 DC   1101  1100   MOD01  1R/M  (disp-lo),(disp-hi)    FCOMP    long-real
7866 DC   1101  1100   MOD10  0R/M  (disp-lo),(disp-hi)    FSUB     long-real
7867 DC   1101  1100   MOD10  1R/M  (disp-lo),(disp-hi)    FSUBR    long-real
7868 DC   1101  1100   MOD11  0R/M  (disp-lo),(disp-hi)    FDIV     long-real
7869 DC   1101  1100   MOD11  1R/M  (disp-lo),(disp-hi)    FDIVR    long-real
7870 DC   1101  1100   1100   0REG                         FADD     ST(i),ST
7871 DC   1101  1100   1100   1REG                         FMUL     ST(i),ST
7872 DC   1101  1100   1101   0REG                         (2)
7873 The marked encodings are not generated by the language translators. If,
7874 however, the 80287 encounters one of these encodings in the instruction
7875 stream, it will execute it as follows:  FCOM ST(i)
7879 DC   1101  1100   1101   1REG                         (3)
7880 The marked encodings are not generated by the language translators. If,
7881 however, the 80287 encounters one of these encodings in the instruction
7882 stream, it will execute it as follows:  FCOMP ST(i)
7886 DC   1101  1100   1110   0REG                         FSUB     ST(i),ST
7887 DC   1101  1100   1110   1REG                         FSUBR    ST(i),ST
7888 DC   1101  1100   1111   0REG                         FDIV     ST(i),ST
7889 DC   1101  1100   1111   1REG                         FDIVR    ST(i),ST
7890 DD   1101  1101   MOD00  0R/M  (disp-lo),(disp-hi)    FLD      long-real
7891 DD   1101  1101   MOD00  1R/M                         reserved
7892 DD   1101  1101   MOD01  0R/M  (disp-lo),(disp-hi)    FST      long-real
7893 DD   1101  1101   MOD01  1R/M  (disp-lo),(disp-hi)    FSTP     long-real
7894 DD   1101  1101   MOD10  0R/M  (disp-lo),(disp-hi)    FRSTOR   94-bytes
7895 DD   1101  1101   MOD10  1R/M  (disp-lo),(disp-hi)    reserved
7896 DD   1101  1101   MOD11  0R/M  (disp-lo),(disp-hi)    FSAVE    94-bytes
7897 DD   1101  1101   MOD11  1R/M  (disp-lo),(disp-hi)    FSTSW    2-bytes
7898 DD   1101  1101   1100   0REG                         FFREE    ST(i)
7899 DD   1101  1101   1100   1REG                         (4)
7900 The marked encodings are not generated by the language translators. If,
7901 however, the 80287 encounters one of these encodings in the instruction
7902 stream, it will execute it as follows:  FXCH ST(i)
7906 DD   1101  1101   1101   0REG                         FST      ST(i)
7907 DD   1101  1101   1101   1REG                         FSTP     ST(i)
7908 DD   1101  1101   111-   ----                         reserved
7909 DE   1101  1110   MOD00  0R/M  (disp-lo),(disp-hi)    FIADD    word-integer
7910 DE   1101  1110   MOD00  1R/M  (disp-lo),(disp-hi)    FIMUL    word-integer
7911 DE   1101  1110   MOD01  0R/M  (disp-lo),(disp-hi)    FICOM    word-integer
7912 DE   1101  1110   MOD01  1R/M  (disp-lo),(disp-hi)    FICOMP   word-integer
7913 DE   1101  1110   MOD10  0R/M  (disp-lo),(disp-hi)    FISUB    word-integer
7914 DE   1101  1110   MOD10  1R/M  (disp-lo),(disp-hi)    FISUBR   word-integer
7915 DE   1101  1110   MOD11  0R/M  (disp-lo),(disp-hi)    FIDIV    word-integer
7916 DE   1101  1110   MOD11  1R/M  (disp-lo),(disp-hi)    FIDIVR   word-integer
7917 DE   1101  1110   1100   0REG                         FADDP    ST(i),ST
7918 DE   1101  1110   1100   1REG                         FMULP    ST(i),ST
7919 DE   1101  1110   1101   0---                         (5)
7920 The marked encodings are not generated by the language translators. If,
7921 however, the 80287 encounters one of these encodings in the instruction
7922 stream, it will execute it as follows:  FCOMP ST(i)
7926 DE   1101  1110   1101   1000                         reserved
7927 DE   1101  1110   1101   1001                         FCOMPP
7928 DE   1101  1110   1101   101-                         reserved
7929 DE   1101  1110   1101   11--                         reserved
7930 DE   1101  1110   1110   0REG                         FSUBP    ST(i),ST
7931 DE   1101  1110   1110   1REG                         FSUBRP   ST(i),ST
7932 DE   1101  1110   1111   0REG                         FDIVP    ST(i),ST
7933 DE   1101  1110   1111   1REG                         FDIVRP   ST(i),ST
7934 DF   1101  1111   MOD00  0R/M  (disp-lo),(disp-hi)    FILD     word-integer
7935 DF   1101  1111   MOD00  1R/M  (disp-lo),(disp-hi)    reserved
7936 DF   1101  1111   MOD01  0R/M  (disp-lo),(disp-hi)    FIST     word-integer
7937 DE   1101  1110   MOD01  1R/M  (disp-lo),(disp-hi)    FISTP    word-integer
7938 DF   1101  1111   MOD10  0R/M  (disp-lo),(disp-hi)    FBLD     packed-decimal
7939 DF   1101  1111   MOD10  1R/M  (disp-lo),(disp-hi)    FILD     long-integer
7940 DF   1101  1111   MOD11  0R/M  (disp-lo),(disp-hi)    FBSTP    packed-decimal
7941 DF   1101  1111   MOD11  1R/M  (disp-lo),(disp-hi)    FISTP    long-integer
7942 DF   1101  1111   1100   0REG                         (6)
7943 The marked encodings are not generated by the language translators. If,
7944 however, the 80287 encounters one of these encodings in the instruction
7945 stream, it will execute it as follows:  FFREE ST(i) and pop stack
7949 DF   1101  1111   1100   1REG                         (7)
7950 The marked encodings are not generated by the language translators. If,
7951 however, the 80287 encounters one of these encodings in the instruction
7952 stream, it will execute it as follows:  FXCH ST(i)
7956 DF   1101  1111   1101   0REG                         (8)
7957 The marked encodings are not generated by the language translators. If,
7958 however, the 80287 encounters one of these encodings in the instruction
7959 stream, it will execute it as follows:  FSTP ST(i)
7963 DF   1101  1111   1101   1REG                         (9)
7964 The marked encodings are not generated by the language translators. If,
7965 however, the 80287 encounters one of these encodings in the instruction
7966 stream, it will execute it as follows:  FSTP ST(i)
7970 DF   1101  1111   1110   000                          FSTSW AX
7971 DF   1101  1111   1111   XXX                          reserved
7974 Appendix B  Compatibility Between the 80287 NPX and the 8087
7976 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
7978 The 80286/80287 operating in Real-Address mode will execute 8087 programs
7979 without major modification. However, because of differences in the handling
7980 of numeric exceptions by the 80287 NPX and the 8087 NPX, exception-handling
7981 routines may need to be changed.
7983 This appendix summarizes the differences between the 80287 NPX and the 8087
7984 NPX, and provides details showing how 8087 programs can be ported to the
7985 80287.
7987   1.  The 80287 signals exceptions through a dedicated ERROR line to the
7988       80286. The 80287 error signal does not pass through an interrupt
7989       controller (the 8087 INT signal does). Therefore, any
7990       interrupt-controller-oriented instructions in numeric exception
7991       handlers for the 8087 should be deleted.
7993   2.  The 8087 instructions FENI/FNENI and FDISI/FNDISI perform no useful
7994       function in the 80287. If the 80287 encounters one of these opcodes in
7995       its instruction stream, the instruction will effectively be ignored‘‘
7996       none of the 80287 internal states will be updated. While 8087 code
7997       containing these instructions may be executed on the 80287, it is
7998       unlikely that the exception-handling routines containing these 
7999       instructions will be completely portable to the 80287.
8001   3.  Interrupt vector 16 must point to the numeric exception handling
8002       routine.
8004   4.  The ESC instruction address saved in the 80287 includes any leading
8005       prefixes before the ESC opcode. The corresponding address saved in the
8006       8087 does not include leading prefixes.
8008   5.  In Protected-Address mode, the format of the 80287's saved
8009       instruction and address pointers is different than for the 8087. The
8010       instruction opcode is not saved in Protected mode‘‘exception handlers
8011       will have to retrieve the opcode from memory if needed.
8013   6.  Interrupt 7 will occur in the 80286 when executing ESC instructions
8014       with either TS (task switched) or EM (emulation) of the 80286 MSW set
8015       (TS = 1 or EM = 1). If TS is set, then a WAIT instruction will also
8016       cause interrupt 7. An exception handler should be included in 80287
8017       code to handle these situations.
8019   7.  Interrupt 9 will occur if the second or subsequent words of a
8020       floating-point operand fall outside a segment's size. Interrupt 13
8021       will occur if the starting address of a numeric operand falls outside
8022       a segment's size. An exception handler should be included in 80287
8023       code to report these programming errors.
8025   8.  Except for the processor control instructions, all of the 80287
8026       numeric instructions are automatically synchronized by the 80286 CPU‘‘
8027       the 80286 automatically tests the BUSY line from the 80287 to ensure
8028       that the 80287 has completed its previous instruction before executing
8029       the next ESC instruction. No explicit WAIT instructions are required
8030       to assure this synchronization. For the 8087 used with 8086 and 8088
8031       processors, explicit WAITs are required before each numeric
8032       instruction to ensure synchronization. Although 8087 programs having
8033       explicit WAIT instructions will execute perfectly on the 80287 without
8034       reassembly, these WAIT instructions are unnecessary.
8036   9.  Since the 80287 does not require WAIT instructions before each
8037       numeric instruction, the ASM286 assembler does not automatically
8038       generate these WAIT instructions. The ASM86 assembler, however,
8039       automatically precedes every ESC instruction with a WAIT instruction.
8040       Although numeric routines generated using the ASM86 assembler will
8041       generally execute correctly on the 80286/20, reassembly using ASM286
8042       may result in a more compact code image.
8044       The processor control instructions for the 80287 may be coded using
8045       either a WAIT or No-WAIT form of mnemonic. The WAIT forms of these
8046       instructions cause ASM286 to precede the ESC instruction with a
8047       CPU WAIT instruction, in the identical manner as does ASM86.
8049   10. A recommended way to detect the presence of an 80287 in an 80286
8050       system (or an 8087 in an 8086 system) is shown below. It assumes that
8051       the sytem hardware causes the data bus to be high if no 80287 is
8052       present to drive the data lines during the FSTSW (Store 80287 Status
8053       Word) instruction.
8055       FND_287: FNINIT            ; initialize numeric processor.
8056                FSTSTW  STAT      ; store status word into location
8057                                  ; STAT.
8058                MOV     AX,STAT
8059                OR      AL,AL     ; Zero Flag reflects result of OR.
8060                JZ      GOT_287   ; Zero in AL means 80287 is present.
8061       ;
8062       ;    No 80287 Present
8063       ;
8064                SMSW    AX
8065                OR      AX,0004H  ; set EM bit in Machine Status Word.
8066                LMSW    AX        ; to enable software emulation of 287.
8067                JMP     CONTINUE
8068       ;
8069       ;    80287 is present in system
8070       ;
8071       GOT_287: SMSW    AX
8072                OR      AX,0002H  ; set MP bit in Machine Status Word
8073                LMSW    AX        ; to permit normal 80287 operation
8074       ;
8075       ;    Continue . . .
8076       ;
8077       CONTINUE:                  ; and off we go
8079       An 80286/80287 design must place a pullup resistor on one of the low
8080       eight data bus bits of the 80286 to be sure it is read as a high when
8081       no 80287 is present.
8084 Appencix C  Implementing the IEEE P754 Standard
8086 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8088 The 80287 NPX and standard support library software, provides an
8089 implementation of the IEEE "A Proposed Standard for Binary Floating-Point
8090 Arithmetic," Draft 10.0, Task P754, of December 2, 1982. The 80287 Support
8091 Library, described in 80287 Support Library Reference Manual, Order Number
8092 122129, is an example of such a support library.
8094 This appendix describes the relationship between the 80287 NPX and the IEEE
8095 Standard. Where the Standard has options, Intel's choices in implementing
8096 the 80287 are described. Where portions of the Standard are implemented
8097 through software, this appendix indicates which modules of the 80287 Support
8098 Library implement the Standard. Where special software in addition to the
8099 Support Library may be required by your application, this appendix indicates
8100 how to write this software.
8102 This appendix contains many terms with precise technical meanings,
8103 specified in the 754 Standard. Where these terms are used, they have been
8104 capitalized to emphasize the precision of their meanings. The Glossary
8105 provides the definitions for all capitalized phrases in this appendix.
8108 Options Implemented in the 80287
8109 The 80287 SHORT_REAL and LONG_REAL formats conform precisely to the
8110 Standard's Single and Double Floating-Point Numbers, respectively. The 80287
8111 TEMP_REAL format is the same as the Standard's Double Extended format. The
8112 Standard allows a choice of Bias in representing the exponent; the 80287
8113 uses the Bias 16383 decimal.
8115 For the Double Extended format, the Standard contains an option for the
8116 meaning of the minimum exponent combined with a nonzero significand. The
8117 Bias for this special case can be either 16383, as in all the other cases,
8118 or 16382, making the smallest exponent equivalent to the second-smallest
8119 exponent. The 80287 uses the Bias 16382 for this case. This allows the 80287
8120 to distinguish between Denormal numbers (integer part is zero, fraction is
8121 nonzero, Biased exponent is 0) and Unnormal numbers of the same value (same
8122 as the denormal except the Biased Exponent is 1).
8124 The Standard allows flexibility in specifying which NaNs are trapping and
8125 which are nontrapping. The EH287.LIB module of the 80287 Support Library
8126 provides a software implementation of nontrapping NaNs, and defines one
8127 distinction between trapping and nontrapping NaNs: If the most significant
8128 bit of the fractional part of a NaN is 1, the NaN is nontrapping. If it is
8129 0, the NaN is trapping.
8131 When a masked Invalid Operation error involves two NaN inputs, the Standard
8132 allows flexibility in choosing which NaN is output. The 80287 selects the
8133 NaN whose absolute value is greatest.
8136 Areas of the Standard Implemented in Software
8137 There are five areas of the Standard that are not implemented directly in
8138 the 80287 hardware; these areas are instead implemented in software as part
8139 of the 80287 Support Library.
8141   1.  The Standard requires that a Normalizing Mode be provided, in which
8142       any nonnormal operands to functions are automatically normalized
8143       before the function is performed. The NPX provides a "Denormal
8144       operand" exception for this case, allowing the exception handler
8145       the opportunity to perform the normalization specified by the
8146       Standard. The Denormal operand exception handler provided by
8147       EH287.LIB implements the Standard's Normalizing Mode completely for
8148       Single- and Double-precision arguments. Normalizing mode for Double
8149       Extended operands is implemented in EH287.LIB with one non-Standard
8150       feature, discussed in the next section.
8152   2.  The Standard specifies that in comparing two operands whose
8153       relationship is "unordered," the equality test yield an answer of
8154       FALSE, with no errors or exceptions. The 80287 FCOM and FTST
8155       instructions themselves issue an Invalid Operation exception in this
8156       case. The error handler EH287.LIB filters out this Invalid Operation
8157       error using the following convention: Whenever an FCOM or FTST
8158       instruction is followed by a MOV AX,AX instruction (8BC0 Hex), and
8159       neither argument is a trapping NaN, the error handler will assume that
8160       a Standard equality comparison was intended, and return the correct
8161       answer with the Invalid Operation exception flag erased. Note that the
8162       Invalid Operation exception must be unmasked for this action to
8163       occur.
8165   3.  The Standard requires that two kinds of NaN's be provided: trapping
8166       and nontrapping. Nontrapping NaNs will not cause further Invalid
8167       Operation errors when they occur as operands to calculations. The NPX
8168       hardware directly supports only trapping NaN's; the EH287.LIB
8169       software implements nontrapping NaNs by returning the correct answer
8170       with the Invalid Operation exception flag erased. Note that the
8171       Invalid Operation exception must be unmasked for this action to occur.
8173   4.  The Standard requires that all functions that convert real numbers to
8174       integer formats automatically normalize the inputs if necessary. The
8175       integer conversion functions contained in CEL287.LIB fully meet the
8176       Standard in this respect; the 80287 FIST instruction alone does not
8177       perform this normalization.
8179   5.  The Standard specifies the remainder function which is provided by
8180       mqerRMD in CEL287.LIB. The 80287 FPREM instruction returns answers
8181       within a different range.
8184 Additional Software to Meet the Standard
8185 There are two cases in which additional software is required in conjunction
8186 with the 80287 Support Library in order to meet the standard. The 80287
8187 Support Library does not provide this software in the interest of saving
8188 space and because the vast majority of applications will never encounter
8189 these cases.
8191   1.  When the Invalid Operation exception is masked, Nontrapping NaNs are
8192       not implemented fully. Likewise, the Standard's equality test for
8193       "unordered" operands is not implemented when the Invalid Operation
8194       exception is masked. Programmers can simulate the Standard notion of
8195       a masked Invalid Operation exception by unmasking the 80287 Invalid
8196       Operation exception, and providing an Invalid Operation exception
8197       handler that supports nontrapping NaNs and the equality test, but
8198       otherwise acts just as if the Invalid Operation exception were
8199       masked. The 80287 Support Library Reference Manual contains examples
8200       for programming this handler in both ASM286 andPL/M-286.
8202   2.  In Normalizing Mode, Denormal operands in the TEMP_REAL format are
8203       converted to 0 by EH287.LIB, giving sharp Underflow to 0. The Standard
8204       specifies that the operation be performed on the real numbers
8205       represented by the denormals, giving gradual underflow. To correctly
8206       perform such arithmetic while in Normalizing Mode, programmers would
8207       have to normalize the operands into a format identical to TEMP_REAL
8208       except for two extra exponent bits, then perform the operation on
8209       those numbers. Thus, software must be written to handle the 17-bit
8210       exponent explicitly.
8212 In designing the EH287.LIB, it was felt that it would be a disadvantage to
8213 most users to increase the size of the Normalizing routine by the amount
8214 necessary to provide this expanded arithmetic. Because the TEMP_REAL
8215 exponent field is so much larger than the LONG_REAL exponent field, it is
8216 extremely unlikely that TEMP_REAL underflow will be encountered in most
8217 applications.
8219 If meeting the Standard is a more important criterion for your application
8220 than the choice between Normalizing and warning modes, then you can select
8221 warning mode (Denormal operand exceptions masked), which fully meets the
8222 Standard.
8224 If you do wish to implement the Normalization of denormal operands in
8225 TEMP_REAL format using extra exponent bits, the list below indicates some
8226 useful pointers about handling Denormal operand exceptions:
8228   1.  TEMP_REAL numbers are considered Denormal by the NPX whenever the
8229       Biased Exponent is 0 (minimum exponent). This is true even if the
8230       explicit integer bit of the significand is 1. Such numbers can occur
8231       as the result of Underflow.
8233   2.  The 80287 FLD instruction can cause a Denormal Operand error if a
8234       number is being loaded from memory. It will not cause this exception
8235       if the number is being loaded from elsewhere in the 80287 stack.
8237   3.  The 80287 FCOM and FTST instructions will cause a Denormal Operand
8238       exception for unnormal operands as well as for denormal operands.
8240   4.  In cases where both the Denormal Operand and Invalid Operation
8241       exceptions occur, you will want to know which is signalled first. When
8242       a comparison instruction operates between a nonexistent stack element
8243       and a denormal number in 80286 memory, the D and I exceptions are
8244       issued simultaneously. In all other situations, a Denormal Operand
8245       exception takes precedence over a nonstack Invalid operation
8246       exception, while a stack Invalid Operation exception takes precedence
8247       over a Denormal Operand exception.
8250 Glossary of 80287 and Floating-Point Terminology
8252 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8254 This glossary defines many terms that have precise technical meanings as
8255 specified in the IEEE 754 Standard. Where these terms are used, they have
8256 been capitalized to emphasize the precision of their meanings.
8258 Affine Mode:
8259   a state of the 80287, selected in the 80287 Control Word, in which
8260   infinities are treated as having a sign. Thus, the values +INFINITY and
8261   -INFINITY are considered different; they can be compared with finite
8262   numbers and with each other.
8264 Base:
8265   (1) a term used in logarithms and exponentials. In both contexts, it is
8266   a number that is being raised to a power. The two equations (y = log
8267   base b of x) and (b^(y) = x) are the same.
8269 Base:
8270   (2) a number that defines the representation being used for a string of
8271   digits. Base 2 is the binary representation; Base 10 is the decimal
8272   representation; Base 16 is the hexadecimal representation. In each case,
8273   the Base is the factor of increased significance for each succeeding
8274   digit (working up from the bottom).
8276 Bias:
8277   the difference between the unsigned Integer that appears in the Exponent
8278   field of a Floating-Point Number and the true Exponent that it
8279   represents. To obtain the true Exponent, you must subtract the Bias from
8280   the given Exponent. For example, the Short Real format has a Bias of 127
8281   whenever the given Exponent is nonzero. If the 8-bit Exponent field
8282   contains 10000011, which is 131, the true Exponent is 131-127, or +4.
8284 Biased Exponent:
8285   the Exponent as it appears in a Floating-Point Number, interpreted as an
8286   unsigned, positive number. In the above example, 131 is the Biased
8287   Exponent.
8289 Binary Coded Decimal:
8290   a method of storing numbers that retains a base 10 representation. Each
8291   decimal digit occupies 4 full bits (one hexadecimal digit). The hex
8292   values A through F (1010 through 1111) are not used. The 80287 supports
8293   a Packed Decimal format that consists of 9 bytes of Binary Coded Decimal
8294   (18 decimal digits) and one sign byte.
8296 Binary Point:
8297   an entity just like a decimal point, except that it exists in binary
8298   numbers. Each binary digit to the right of the Binary Point is
8299   multiplied by an increasing negative power of two.
8301 C3‘‘C0:
8302   the four "condition code" bits of the 80287 Status Word. These bits are
8303   set to certain values by the compare, test, examine, and remainder
8304   functions of the 80287.
8306 Characteristic:
8307   a term used for some non-Intel computers, meaning the Exponent field of
8308   a Floating-Point Number.
8310 Chop:
8311   to set the fractional part of a real number to zero, yielding the
8312   nearest integer in the direction of zero.
8314 Control Word:
8315   a 16-bit 80287 register that the user can set, to determine the modes of
8316   computation the 80287 will use, and the error interrupts that will be
8317   enabled.
8319 Denormal:
8320   a special form of Floating-Point Number, produced when an Underflow
8321   occurs. On the 80287, a Denormal is defined as a number with a Biased
8322   Exponent that is zero. By providing a Significand with leading zeros,
8323   the range of possible negative Exponents can be extended by the number
8324   of bits in the Significand. Each leading zero is a bit of lost accuracy,
8325   so the extended Exponent range is obtained by reducing significance.
8327 Double Extended:
8328   the Standard's term for the 80287 Temporary Real format, with more
8329   Exponent and Significand bits than the Double (Long Real) format, and an
8330   explicit Integer bit in the Significand.
8332 Double Floating Point Number:
8333   the Standard's term for the 80287's 64-bit Long Real format.
8335 Environment:
8336   the 14 bytes of 80287 registers affected by the FSTENV and FLDENV
8337   instructions. It encompasses the entire state of the 80287, except for
8338   the 8 Temporary Real numbers of the 80287 stack. Included are the
8339   Control Word, Status Word, Tag Word, and the instruction, opcode, and
8340   operand information provided by interrupts.
8342 Exception:
8343   any of the six error conditions (I, D, O, U, Z, P) signalled by the
8344   80287.
8346 Exponent:
8347   (1) any power that is raised by an exponential function. For example,
8348   the operand to the function mqerEXP is an Exponent. The Integer operand
8349   to mqerYI2 is an Exponent.
8351 Exponent:
8352   (2) the field of a Floating-Point Number that indicates the magnitude of
8353   the number. This would fall under the above more general definition (1),
8354   except that a Bias sometimes needs to be subtracted to obtain the
8355   correct power.
8357 Floating-Point Number:
8358   a sequence of data bytes that, when interpreted in a standardized way,
8359   represents a Real number. Floating-Point Numbers are more versatile than
8360   Integer representations in two ways. First, they include fractions.
8361   Second, their Exponent parts allow a much wider range of magnitude than
8362   possible with fixed-length Integer representations.
8364 Gradual Underflow:
8365   a method of handling the Underflow error condition that minimizes the
8366   loss of accuracy in the result. If there is a Denormal number that
8367   represents the correct result, that Denormal is returned. Thus, digits
8368   are lost only to the extent of denormalization. Most computers return
8369   zero when Underflow occurs, losing all significant digits.
8371 Implicit Integer Bit:
8372   a part of the Significand in the Short Real and Long Real formats that
8373   is not explicitly given. In these formats, the entire given Significand
8374   is considered to be to the right of the Binary Point. A single Implicit
8375   Integer Bit to the left of the Binary Point is always 1, except in one
8376   case. When the Exponent is the minimum (Biased Exponent is 0), the
8377   Implicit Integer Bit is 0.
8379 Indefinite:
8380   a special value that is returned by functions when the inputs are such
8381   that no other sensible answer is possible. For each Floating-Point
8382   format there exists one Nontrapping NaN that is designated as the
8383   Indefinite value. For binary Integer formats, the negative number
8384   furthest from zero is often considered the Indefinite value. For the
8385   80287 Packed Decimal format, the Indefinite value contains all 1's in
8386   the sign byte and the uppermost digits byte.
8388 Infinity:
8389   a value that has greater magnitude than any Integer or any Real number.
8390   The existence of Infinity is subject to heated philosophical debate.
8391   However, it is often useful to consider Infinity as another number,
8392   subject to special rules of arithmetic. All three Intel Floating-Point
8393   formats provide representations for +INFINITY and -INFINITY. They
8394   support two ways of dealing with Infinity: Projective (unsigned) and
8395   Affine (signed).
8397 Integer:
8398   a number (positive, negative, or zero) that is finite and has no
8399   fractional part. Integer can also mean the computer representation for
8400   such a number: a sequence of data bytes, interpreted in a standard way.
8401   It is perfectly reasonable for Integers to be represented in a
8402   Floating-Point format; this is what the 80287 does whenever an Integer is
8403   pushed onto the 80287 stack.
8405 Invalid Operation:
8406   the error condition for the 80287 that covers all cases not covered by
8407   other errors. Included are 80287 stack overflow and underflow, NaN
8408   inputs, illegal infinite inputs, out-of-range inputs, and illegal
8409   unnormal inputs.
8411 Long Integer:
8412   an Integer format supported by the 80287 that consists of a 64-bit Two's
8413   Complement quantity.
8415 Long Real:
8416   a Floating-Point Format supported by the 80287 that consists of a sign,
8417   an 11-bit Biased Exponent, an Implicit Integer Bit, and a 52-bit
8418   Significand‘‘a total of 64 explicit bits.
8420 Mantissa:
8421   a term used for some non-Intel computers, meaning the Significand of a
8422   Floating-Point Number.
8424 Masked:
8425   a term that applies to each of the six 80287 Exceptions I,D,Z,O,U,P. An
8426   exception is Masked if a corresponding bit in the 80287 Control Word is
8427   set to 1. If an exception is Masked, the 80287 will not generate an
8428   interrupt when the error condition occurs; it will instead provide its
8429   own error recovery.
8431 NaN:
8432   an abbreviation for Not a Number; a Floating-Point quantity that does
8433   not represent any numeric or infinite quantity. NaNs should be returned
8434   by functions that encounter serious errors. If created during a sequence
8435   of calculations, they are transmitted to the final answer and can
8436   contain information about where the error occurred.
8438 Nontrapping NaN:
8439   a NaN in which the most significant bit of the fractional part of the
8440   Significand is 1. By convention, these NaNs can undergo certain
8441   operations without visible error. Nontrapping NaNs are implemented for
8442   the 80287 via the software in EH87.LIB.
8444 Normal:
8445   the representation of a number in a Floating-Point format in which the
8446   Significand has an Integer bit 1 (either explicit or Implicit).
8448 Normalizing Mode:
8449   a state in which nonnormal inputs are automatically converted to normal
8450   inputs whenever they are used in arithmetic. Normalizing Mode is
8451   implemented for the 80287 via the software in EH87.LIB.
8453 NPX:
8454   Numeric Processor Extension. This is the 80287.
8456 Overflow:
8457   an error condition in which the correct answer is finite, but has
8458   magnitude too great to be represented in the destination format.
8460 Packed Decimal:
8461   an Integer format supported by the 80287. A Packed Decimal number is a
8462   10-byte quantity, with nine bytes of 18 Binary Coded Decimal digits, and
8463   one byte for the sign.
8465 Pop:
8466   to remove from a stack the last item that was placed on the stack.
8468 Precision Control:
8469   an option, programmed through the 80287 Control Word, that allows all
8470   80287 arithmetic to be performed with reduced precision. Because no
8471   speed advantage results from this option, its only use is for strict
8472   compatibility with the IEEE Standard, and with other computer
8473   systems.
8475 Precision Exception:
8476   an 80287 error condition that results when a calculation does not return
8477   an exact answer. This exception is usually Masked and ignored; it is
8478   used only in extremely critical applications, when the user must know if
8479   the results are exact.
8481 Projective Mode:
8482   a state of the 80287, selected in the 80287 Control Word, in which
8483   infinities are treated as not having a sign. Thus the values +INFINITY
8484   and -INFINITY are considered the same. Certain operations, such as
8485   comparison to finite numbers, are illegal in Projective Mode but legal
8486   in Affine Mode. Thus Projective Mode gives you a greater degree of error
8487   control over infinite inputs.
8489 Pseudo Zero:
8490   a special value of the Temporary Real format. It is a number with a zero
8491   significand and an Exponent that is neither all zeros or all ones.
8492   Pseudo zeros can come about as the result of multiplication of two
8493   Unnormal numbers; but they are very rare.
8495 Real:
8496   any finite value (negative, positive, or zero) that can be represented
8497   by a decimal expansion. The fractional part of the decimal expansion can
8498   contain an infinite number of digits. Reals can be represented as the
8499   points of a line marked off like a ruler. The term Real can also refer
8500   to a Floating-Point Number that represents a Real value.
8502 Short Integer:
8503   an Integer format supported by the 80287 that consists of a 32-bit Two's
8504   Complement quantity. Short Integer is not the shortest 80287 Integer
8505   format‘‘the 16-bit Word Integer is.
8507 Short Real:
8508   a Floating-Point Format supported by the 80287, which consists of a
8509   sign, an 8-bit Biased Exponent, an Implicit Integer Bit, and a 23-bit
8510   Significand‘‘a total of 32 explicit bits.
8512 Significand:
8513   the part of a Floating-Point Number that consists of the most
8514   significant nonzero bits of the number, if the number were written out
8515   in an unlimited binary format. The Significand alone is considered to
8516   have a Binary Point after the first (possibly Implicit) bit; the Binary
8517   Point is then moved according to the value of the Exponent.
8519 Single Extended:
8520   a Floating-Point format, required by the Standard, that provides greater
8521   precision than Single; it also provides an explicit Integer Significand
8522   bit. The 80287's Temporary Real format meets the Single Extended
8523   requirement as well as the Double Extended requirement.
8525 Single Floating-Point Number:
8526   the Standard's term for the 80287's 32-bit Short Real format.
8528 Standard:
8529   "a Proposed Standard for Binary Floating-Point Arithmetic," Draft 10.0
8530   of IEEE Task P754, December 2, 1982.
8532 Status Word:
8533   A 16-bit 80287 register that can be manually set, but which is usually
8534   controlled by side effects to 80287 instructions. It contains condition
8535   codes, the 80287 stack pointer, busy and interrupt bits, and error
8536   flags.
8538 Tag Word:
8539   a 16-bit 80287 register that is automatically maintained by the 80287.
8540   For each space in the 80287 stack, it tells if the space is occupied by
8541   a number; if so, it gives information about what kind of number.
8543 Temporary Real:
8544   the main Floating-Point Format used by the 80287. It consists of a sign,
8545   a 15-bit Biased Exponent, and a Significand with an explicit Integer bit
8546   and 63 fractional-part bits.
8548 Transcendental:
8549   one of a class of functions for which polynomial formulas are always
8550   approximate, never exact for more than isolated values. The 80287
8551   supports trigonometric, exponential, and logarithmic functions; all are
8552   Transcendental.
8554 Trapping NaN:
8555   a NaN that causes an I error whenever it enters into a calculation or
8556   comparison, even a nonordered comparison.
8558 Two's Complement:
8559   a method of representing Integers. If the uppermost bit is 0, the number
8560   is considered positive, with the value given by the rest of the bits. If
8561   the uppermost bit is 1, the number is negative, with the value obtained
8562   by subtracting (2^(bit count)) from all the given bits. For example, the
8563   8-bit number 11111100 is -4, obtained by subtracting 2^(8) from 252.
8565 Unbiased Exponent:
8566   the true value that tells how far and in which direction to move the
8567   Binary Point of the Significand of a Floating-Point Number. For example,
8568   if a Short Real Exponent is 131, we subtract the Bias 127 to obtain the
8569   Unbiased Exponent +4. Thus, the Real number being represented is the
8570   Significand with the Binary Point shifted 4 bits to the right.
8572 Underflow:
8573   an error condition in which the correct answer is nonzero, but has a
8574   magnitude too small to be represented as a Normal number in the
8575   destination Floating-Point format. The Standard specifies that an
8576   attempt be made to represent the number as a Denormal.
8578 Unmasked:
8579   a term that applies to each of the six 80287 Exceptions: I,D,Z,O,U,P. An
8580   exception is Unmasked if a corresponding bit in the 80287 Control Word
8581   is set to 0. If an exception is Unmasked, the 80287 will generate an
8582   interrupt when the error condition occurs. You can provide an interrupt
8583   routine that customizes your error recovery.
8585 Unnormal:
8586   a Temporary Real representation in which the explicit Integer bit of the
8587   Significand is zero, and the exponent is nonzero. We consider Unnormal
8588   numbers distinct from Denormal numbers.
8590 Word Integer:
8591   an Integer format supported by both the 80286 and the 80287 that
8592   consists of a 16-bit Two's Complement quantity.
8594 Zero divide:
8595   an error condition in which the inputs are finite, but the correct
8596   answer, even with an unlimited exponent, has infinite magnitude.
8599 Index
8600 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8604 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8605 Address Modes
8606 Architecture
8607 Arithmetic Instructions
8608 ASM 286
8609 Automatic Exception Handling
8613 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8614 Binary Integers
8618 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8619 Comparison Instructions
8620 Compatibility Between the 80287 and 8087
8621 Computation Fundamentals
8622 Concurrent (80286 and 80287) Processing
8623 Condition Codes Interpretation
8624 Constant Instructions
8625 Control Word
8629 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8630 Data Synchronization
8631 Data Transfer Instructions
8632 Data Types and Formats
8633  Binary Integers
8634  Decimal Integers
8635  Encoding of Data Type
8636  Infinity Control
8637  Precision Control
8638  Real Numbers
8639  Rounding Control
8640 Decimal Integers
8641 Denormalization
8642 Denormalized Operand
8643 Denormals
8644 Destination Operands
8648 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8649 EM (Emulation Mode) Bit in 80286
8650 Emulation of 80287
8651 Encoding of Data Types
8652 Error Synchronization
8653 Exception Handling Examples
8654 Exception Handling, Numeric Processing
8655 Exceptions, Numeric
8656  Automatic Exception Handling
8657  Handling Numeric Errors
8658  Inexact Result
8659  Invalid Operation
8660  Masked Response
8661  Numeric Overflow and Underflow
8662  Software Exception Handling
8663  Zero Divisor
8664 Exponent Field
8668 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8669 F2XM1 (Exponentiation)
8670 FADD (Add Real)
8671 FADDP (Add Real and POP)
8672 FABS (Absolute Value)
8673 FBLD (Packed Decimal‘‘BCD‘‘Load)
8674 FBSTP (Packed Decimal‘‘BCD‘‘Store and Pop)
8675 FCHS (Change Signs)
8676 FCLEX/FNCLEX (Clear Exceptions)
8677 FCOM (Compare Real)
8678 FCOMP (Compare Real and Pop)
8679 FCOMPP (Compare Real and Pop Twice)
8680 FDECSTP (Decrement Stack Pointer)
8681 FDISI/FNDISI
8682 FDIV (Divide Real)
8683 FDIV DWORD PTR (Division, Single Precision)
8684 FDIVP (Divide Real and Pop)
8685 FDIVR (Divide Real Reversed)
8686 FDIVRP (Divide Real Reversed and Pop)
8687 FENI/FNENI
8688 FFREE (Free Register)
8689 FIADD (Integer Add)
8690 FICOM (Integer Compare)
8691 FICOMP (Integer Compare and Pop)
8692 FIDIV (Integer Divide)
8693 FIDIVR (Integer Divide Reversed)
8694 FILD (Integer Load)
8695 FIMUL (Integer Multiply)
8696 FINCSTP (Increment Stack Pointer)
8697 FINIT/FNINIT (Initialize Processor)
8698 FIST (Integer Store)
8699 FISTP (Integer Store and Pop)
8700 FISUB (Integer Subtract)
8701 FISUBR (Integer Subtract Reversed)
8702 FLD (Load Real)
8703 FLD1 (Load One)
8704 FLDCW (Load Control Word)
8705 FLDENV (Load Environment)
8706 FLDL2E (Load Log Base 2 of e)
8707 FLDL2T (Load Log Base 2 of 10)
8708 FLDLG2 (Load Log Base 3 10 of 2)
8709 FLDLN2 (Load Log Base e of 2)
8710 FLDPI (Load PI)
8711 FLDZ (Load Zero)
8712 FMUL (Multiply Real)
8713 FMULP (Multiply Real and Pop)
8714 FNOP (No Operation)
8715 FPATAN (Partial Arctangant)
8716 FPREM (Partial Remainder)
8717 FPTAN (Partial Tangent)
8718 FRNDINT (Round to Integer)
8719 FRSTOR (Restore State)
8720 FSAVE, FNSAVE (Save State)
8721 FSCALE (Scale)
8722 FSETPM (Set Protected Mode)
8723 FSQRT (Square Root)
8724 FST (Store Real)
8725 FSTCW/FNSTCW (Store Control Word)
8726 FSTENV/FNSTENV (Store Environment)
8727 FSTP (Store Real and Pop)
8728 FSTSW/FNSTSW (Store Status Word)
8729 FSTSW AX, FNSTSW AX (Store Status Word in AX)
8730 FSUB (Subtract Real)
8731 FSUBP (Subtract Real and Pop)
8732 FSUBR (Subtract Real Reversed)
8733 FSUBRP (Subtract Real Reversed and Pop)
8734 FTST (Test)
8735 FWAIT (CPU Wait)
8736 FXAM (Examine)
8737 FXCH (Exchange Registers)
8738 FXTRACT (Extract Exponent and Significand)
8739 FYL2X (Logarithm‘‘of x)
8740 FYL2XP1 (Logarithm‘‘of x+1)
8744 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8745 GET$REAL$ERROR (Store, then Clear, Exception Flags)
8749 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8750 Handling Numeric Errors
8751 Hardware Interface
8755 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8756 I/O Locations (Dedicated and Reserved)
8757 IEEE P754 Standard, Implementation
8758 Indefinite
8759 Inexact Result
8760 Infinity
8761 Infinity Control
8762 INIT$REAL$MATH$UNIT (Initialize Processor Procedure)
8763 Initialization and Control
8764 Instruction Coding and Decoding
8765 Instruction Execution Times
8766 Instruction Length
8767 Integer Bit
8768 Introduction to Numeric Processor 80287
8769 Invalid Operation
8773 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8774 Long Integer Format
8775 Long Real Format
8779 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8780 Machine Instruction Encoding and Decoding
8781 Masked Response
8782 MP (Math Present) Flag
8786 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8787 NaN (Not a Number)
8788 NO-WAIT FORM
8789 Nonnormal Real Numbers
8790 Number System
8791 Numeric Exceptions
8792 Numeric Operands
8793 Numeric Overflow and Underflow
8794 Numeric Processor Overview
8798 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8799 Output Format
8800 Overflow
8804 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8805 Packed Decimal Notation
8806 Precision Control
8807 PLM-286
8808 Pointers (INstruction/Data)
8809 Processor Control Instructions
8810 Programming Examples,
8811  Comparative
8812  Conditional Branching
8813  Exception Handling
8814  Floating Point to ASCII Conversion
8815  Function Partitioning
8816  Special Instructions
8817 Programming Interface
8818 Pseudo zeros and zeros
8822 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8823 Real Number Range
8824 Real Numbers
8825 Recognizing the 80287
8826 Register Stack
8827 RESTORE$REAL$STATUS (Restore Processor State)
8828 Rounding Control
8832 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8833 SAVE$REAL$STATUS (Save Processor State)
8834 Scaling
8835 SET$REAL$MODE (Set Exception Masks,Rounding Precision, and Infinity
8836    Controls)
8837 Short Integer Format
8838 Short Real Format
8839 Significand
8840 Software Exception Handling
8841 Source Operands
8842 Status Word
8846 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8847 Tag Word
8848 Temporary Real Format
8849 Transcendental Instructions
8850 Trigonometric Calculation Examples
8854 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8855 Underflow
8856 Unnormals
8857 Upgradability
8861 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8862 WAIT Form
8863 Word Integer Format
8867 ‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘
8868 Zero Divisor
8871 99""*-\98]PR_:*pRDWFL\x03^AWJU\x06FIL\bSLXEX\x0elnb\x17\x0e\x0e\x0f\x1e  U\x01\br\x17\x16szxu\x10<\x13wytx\x7f3\x1fzuw|\x197\x18~\f\x1a